1.集合的由来:
对象用于封装特有数据,对象多了需要存储,就需要结合容器进行存储。
1.2集合的特点:
1.用于存储对象的容器。
2.集合长度是可变的。
3.集合中不可以存储基本数据类型值。
1.3
集合容器因为内部数据结构不同,有多中具体容器,不断向上抽取,就形成了集合框架,位于最顶层的就是Collection接口。
1.4Collection的常见方法:
· 1.添加。
boolean add(Object obj);
boolean addAll(Collection coll);
2.删除。
boolean remove(Object obj);移除相同的元素
boolean removeAll(Collection coll);
将两个集合中的相同元素从调用removeAll的集合中删除
3.判断。
boolean contains(Object obj);
boolean containsAll(Collection coll);
boolean isEmpty();判断集合中是否有元素。
4.获取。
int size();获取长度
Iterator iterator();
取出元素的方式:迭代器该对象必须依赖具体的容器,
因为每一个容器的数据结构都不同,
所以该迭代器对象是在容器内部实现的,
对于使用容器者而言,具体的实现不重要,
只要通过容器获取到实现迭代器的对象即可。
for(Iterator it = coll.iterator(); it.hasNext();){
System.out.println(it.next());}
5.其他。
boolean retainAll(Collection coll);取交集
Object[] toArray();将集合转为数组。
注意
在迭代器过程中,不要使用集合操作元素,容易出现异常。
可以使用Iterator接口的子接口ListIterator来完成在迭代过程中对元素的更多操作。
List list = new ArrayList();
list.add("abc1");
list.add("abc2");
list.add("abc3");
list.add("abc4");
for(ListIterator it = list.listIterator(); it.hasNext();){ //获取列表迭代器对象
//它可以实现在迭代过程中完成对元素的增删改查
//注意。只有list集合具备该迭代功能
Object obj = it.next();
if(obj.equals("abc2")){
it.set("ABC");
}else{
System.out.println(obj);
}
}
System.out.println(list);
2.1Collection常用的子类接口:
List:有序(存取的顺序一致),元素都是有索引的,元素可以重复。
Set:元素不能重复,无序。
2.2.1List:特有的常见方法:它们有一个共性就是都可以操作角标。
1.添加
void add(index,element);
void add(index,collection);
2.删除
Object remove(index);
3.修改
Object set(index,element);
4.获取
Object get(index);
int indexOf(object);
int lastIndexOf(object);
List subLisyt(from,to);
list可以完成对元素(对象)的增删改查。
2.2.2 list的子类
vector:内部是数组数据结构,是同步的,几乎不用了,增删改查的速度都很慢。
ArrayList:内部是数组数据结构,是不同步的,代替了V为此投入,查询速度很快。
LinkedList:内部是链表数据结构,是不同的,增删元素的速度很快。
3 linkedList:
addFirst();在表头位置插入。
addLast();在表尾位置插入。
getFirst();得到表头元素,获取但不移除,如果链表为空,抛出异常。
getLast();得到表尾元素。
jdk1.6以后
peekFirst();获取表头元素,获取但不移除,如果链表为空返回null
peekLast();
removeFirst();获取第一个元素并且移除,如果链表为空,抛出异常。
removeLast();获取最后一个元素并且移除。
jdk 1.6之后
pollFirst();获取第一个元素而且移除,如果链表为空,返回null
pollLast();获取最后一个元素而且移除。
3.2 LinkedList练习
LinkedList练习
/*
* 请使用LinkedList来模拟一个堆栈或者队列的数据结构。
*
*堆栈:特点先进后出First In Last Out FILO
*
*队列:特点先进先出First In First Out FIFO
*
*我们应该描述这样一个容器,给使用提供一个容器对象完成这种结构中的一种。
*
*/
import java.util.LinkedList;
public class DuiLie{
LinkedList link;
DuiLie(){
link = new LinkedList();
//类加载时就创建了一个LinkedList对象。
}
public void myAdd(Object obj){
link.addLast(obj);//在表尾掺入
}
public Object myGet(){
return link.removeFirst();//返回并移除第一个元素
}
public boolean myIsEmpty(){
return link.isEmpty();//判断容器是够为空。
}
}
public class LinkedListTest {
public static void main(String[] args){
DuiLie d = new DuiLie();
d.myAdd("abc1");
d.myAdd("abc2");
d.myAdd("abc3");
d.myAdd("abc4");
while(!d.myIsEmpty()){
System.out.println(d.myGet());
}
}
}
4.1
(1) ArrayList集合存储自定义对象
ArrayList Test
//创建自定义对象
public class Person {
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
}
public class ArrayListTset_1{
public static void main(String[] args){
ArrayList al = new ArrayList();
//存储自定义对象
a1.add(new Person("Gailun",21));
a1.add(new Person("WangZhaoJun",23));
a1.add(new Person("LiBai",26));
a1.add(new Person("GaiLun",21));
/*
add方法是可以存储所有的对象的,它会把要存储的对象
自动类型提升为Object类,所以在取元素(对象)的时候
要进行强制类型转换,然后在一系列操作。
*/
//获取元素(对象)
for(Iterator it = al.iterator; it.hasNext();){
Person p = (Person) it.next();
System.out.println(p.getName()+" ,"+p.getAge())
}
}
}
4.2 ArrayList定义功能去除相同的元素。
/*
定义功能去除ArrayList中的重复元素。
*/
public class Person {
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
public String toString(){
return this.name+" "+this.age;
}
public boolean equals(Object obj){
if(this == obj)//判断是否是同一个对象。
return true;
if(!(obj instanceof Person)){//判断是否是一个类
throw new ClassCastException();
}//判断是否是相同的类。
Person p = (Person)obj;
return this.name.equals(p.name) && this.age==p.age
//比较名字和年龄是否都相同,相同则认为是一个人。
}
}
Public class ArrayListTest_2{
public static void main(String[] args){
ArrayList al = new ArrayList();
a1.add(new Person("Gailun",21));
a1.add(new Person("WangZhaoJun",23));
a1.add(new Person("LiBai",26));
a1.add(new Person("GaiLun",21));
System.out.println(al);
a1 = getSingleElement(al);
System.out.println(al);
}
public static ArrayList getSingleElement(ArrayList al){
//定义了一个临时容器
ArrayList temp = new ArrayList();
//使用迭代器遍历al容器
for(Iterator it = al.iterator; it.hasNext();){
Person p = (Person) it.next();
if(!temp.contains(p)){
//判断临时容器中是否含有这个对象,如果含有就不存储,没有就存储。
/*
contains方法是靠equals方法来判断是否相同的,
如果要按指定方式判断,就要重写Person中的equals方法。
*/
temp.add(p)
}
}
return temp
}
}
5.
Set: 元素不可以重复,是无序的。此接口中的方法和Collection一致。
Set接口下有两个常用的子类HashSet和TreeSet.
5.2 HashSet
内部数据结构是哈希表,是不同步的,存储元素的时候,
使用的是hashCode方法来确定位置,如果位置相同,
再通过元素的equals来确定是否相同。
注意,在使用自定义对象的时候要重写equals和hashCode方法。
HashSetTest
/*
1.往hashSet集合中存储字符串,会按照默认的方式保证集合元素的唯一性,
如果存储的是自定义对象,则要根据对象的特点重新复写hashCode和equals方法
来保证对象的唯一性。
2.往hashSet集合中存储Person对象,如果姓名相同,视为同一人,视为相同元素,
使用的是hashCode方法来确定位置,如果位置相同,再通过equals方法来确定是否相同。
equals默认的比较地址,要重写equals方法和hashCode方法。*/
public class Person {
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
public String toString(){
return this.name+" "+this.age;
}
public int hashCode() {
return this.name.hashCode()+this.age*27;
//为了保证哈希值得唯一性,要根据对象的属性设置哈希值
//如果哈希值相同在利用equals方法来判断
//hashSet要利用hashCode和equals方法来保证元素的唯一性。
}
public boolean equals(Object obj){
if(this == obj)//判断是否是同一个对象。
return true;
if(!(obj instanceof Person)){//判断是否是一个类
throw new ClassCastException();
}//判断是否是相同的类。
Person p = (Person)obj;
return this.name.equals(p.name) && this.age==p.age
//比较名字和年龄是否都相同,相同则认为是一个人。
}
}
public class HashSetTest {
public static void main(String[] args){
HashSet hs = new LinkedHashSet();
hs.add(new Person("Wang",18));
hs.add(new Person("Li",20));
hs.add(new Person("Huang",18));
hs.add(new Person("Wang",18));
for (Iterator it = hs.iterator() ; it.hasNext();){
Person p = (Person) it.next();
System.out.println(p.getName()+"--"+p.getAge());
}
}
}
5.3 TreeSet
可以对set集合中的元素进行排序,是不同步的。
判断元素的唯一性的方式:
就是根据compareTo方法的返回结果是否为0,为0就是相同元素不存。
5.3.2 TreeSet对元素进行排序的两种方式
方式一:让元素自身具备比较功能,元素需要实现Comparable接口,覆盖compareTo方法。
public class Person implements Comparable{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
public String toString(){
return this.name+" "+this.age;
}
public int comapreTo(Object obj){
if (!(obj instanceof Person)){
throw new ClassCastException();
}//判断健壮性
Person p = (Person) obj;
int temp = this.age-p.age;//先判断年龄在判断姓名。
return temp==0?this.name.compareTo(p.name):temp;
}
}
public class TreeSetDemo{
public static void main(String[] args){
TreeSet ts = new TreeSet();
ts.add(new Person("GaiLun",25));
ts.add(new Person("DaoQiao",22));
ts.add(new Person("XiaoQiao",23));
ts.add(new Person("WangZhaoJun",25));
ts.add(new Person("LiBai",27));
ts.add(new Person("HuangZhong",29));
for (Iterator it = ts.iterator(); it.hasNext();){
Person p = (Person) it.next();
System.out.println(p.getName()+"-- "+p.getAge());
}
}
}
第二种比较方式:让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。将该类对象作为参数传递给TreeSet集合的构造函数。
TreeSet ts = new TreeSet(new ComparatorByName());
public class Person {
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
public String toString(){
return this.name+" "+this.age;
}
}
public class ComparatorByName implements Comparator{
public int compare(Object o1, Object o2){
if (!(o1 instanceof Person)|| !(o2 instanceof Person)){
throw new ClassCastException();
}
Person p1 = (Person)o1;
Person p2 = (Person)o2;
int temp = p1.getName().compareTo(p2.getName());
//先比较名字,在比较年龄。
return temp==0?p1.getAge()-p2.getAge():temp;
//return 1;
//返回1就是怎么存就怎么取。
//返回-1就是怎么逆序取出
}
}
public static class ComparatorByLens implements Comparator{
public int compare(Object o1, Object o2) {
if (!(o1 instanceof String ) || !(o1 instanceof String ))
{
throw new ClassCastException();
}
String s1 = (String) o1;
String s2 = (String) o2;
int temp = s1.length()-s2.length();//首先比较字符串的长度
return temp==0?s1.compareTo(s2):temp;//然后比较字符串的内容
}
6.集合的一些使用技巧
需要唯一么?
需要:Set
需要制定顺序么?
需要:TreeSet
不需要:HashSet
想要一个存取一致的顺序:LinkedHashSet
不需要:List
需要频繁增删么?
需要:LinkedList
不需要:ArrayList
List
ArrayList
LinkedList
Set
HashSet
TreeSet
后缀名就是该集合所属的体系,前缀名就是该集合的数据结构。
array:数组查询快,有角标
Link;链表,增删快,add get remove+first last方法
hash:哈希表,唯一性,元素要覆盖hashCode和equals方法。
tree:二叉树,想到排序,想到Comparable和Comparator接口。