公众号:菜鸡干Java 站点:https://www.maliaoblog.cn
集合介绍
Java集合类是一种特别的工具类,可以储存对象,并实现了常用的数据结构,另外还能保存具有映射关系的关联数组。集合大致分为Set,List,Queue,Map四种,其中Set代表无序、不可重复,List代表有序、重复,Map则代表具有映射关系,Java5增加了Queue集合,代表一种队列集合实现。Java集合就像一种容器,把多个对象放到容器中。Java5之前,J集合会丢失对象的数据类型,把所有对象都当成Object类型,从Java5开始增加了泛型,集合可以记住容器中对象的数据类型,从而能编写更简洁的代码。
所有的集合类都位于java.util包下,后来在java.util.concurrent包下提供了多线程集合类。集合类和数组不太一样,数组元素可以是基本数据类型,也可以是对象;而集合只能保存对象(实际保存的是对象的引用变量)。集合类主要由两个接口来实现,Collection和Map,两个根接口。

上图有Map接口的众多实现类,这些类在功能、用法上存在一定的差异,但它们都有一个功能特征,保存的每项数据是Key-value键值对。Map的Key是不可重复的,key用于标识集合集合里的每项数据,如果要查数据,根据Key来获取。添加一个对象到集合中,Set集合无法记住这个元素的顺序,系统无法识别,所以Set里的元素不能重复。
对于这四种集合,其中常用的有:HashSet、TreeSet、ArrayList、ArrayDeque、LinkedList、HashMap和TreeMap等实现类。
Collection和Iterator接口
Collection接口是List,Set,Queue接口的父接口,如果接口没弄明白,可以看看之前的文章Java的异常、多态要点及抽象类和接口。Collection接口定义了如下方法:
| boolean add(Object o) | 向集合里添加一个元素,如果添加成功则返回true |
|---|---|
| boolean addAll(Collection c) | 把集合内元素添加到指定集合,成功返回true |
| void clear() | 清除集合内所有元素,将集合长度变为0 |
| boolean contains(Object o) | 返回集合是否包含指定元素 |
| boolean containsAll(Collection c) | 返回集合是否包含集合c所有元素 |
| boolean isEmpty() | 返回集合是否为空,长度为0返回true |
| Iterator iterator() | 返回一个Iterator对象用于遍历 |
| boolean remove(Object o) | 删除指定元素o,如果有多个删除第一个 |
| boolean retainAll(Collection c) | 从集合中删除集合c里不包含的元素,相当于求和集合c的交集 |
| int size() | 返回集合里元素个数 |
| Object[] toArray() | 将一个集合转换成数组 |
| boolean remove(Collection c) | 从集合中删除集合c里包含的元素 |
具体可阅读API文档,里面有详细信息。编译时可能会输出一些警告,提醒没有使用泛型来限制集合内元素类型,不过之后会提到泛型编程。当使用System.out的println方法来输出集合对象时,将输出[e1,e2...]形式,这是因为所有Collection实现类重写了toString方法,该方法可一次性输出集合中所有元素。如果想依次访问集合中的每一个元素,则需要使用某种遍历方法。
集合的遍历
一、Lambda表达式遍历
Java8为Iterable接口新增了一个forEach方法,参数类型是一个函数式接口,而Iterable接口是Collection接口的父接口,所以Collection集合类也可以调用该方法。当调用Iterable的forEach(Consumer a)方法时,程序将集合元素传给Consumer的accept(T t)抽象方法,然后用Lambda表达式遍历。
Collection names = new HashSet();
names.add("张三");
names.add("李四");
names.forEach(obj ->System.out.println(" "+obj));
二、Java8增强Iterator遍历集合
Iterator接口也是Java集合框架的成员,但它与Collection、Map不一样,它们是用来放对象的,而Iterator则用于遍历Collecton集合中的元素,Iterator对象也被称为迭代器。
Iterator接口定义了如下4种方法:
- boolean hasNext():如果没有遍历完,则返回
true - Object next():返回集合的下一个元素,注意是
Object对象 - void remove():删除集合上一次next方法返回的元素
- void forEachRemaining(Consumer a):Java8新增的方法,该方法可使用
Lambda表达式遍历集合
Collection names = new HashSet();
names.add("张三");
names.add("李四");
Iterator it = names.iterator();
while(it.hasNext()){
String name = (String)it.next();
System.out.println(name);
if(name.equals("张三")){
it.remove();//names.remove(name);将报错
}//迭代时不能改变集合元素的值
}
Iterator仅用于遍历集合,本身不提供装载对象的能力。如果要创建一个Iterator对象,则必须要有一个被遍历的集合,没有集合那要Iterator何用。迭代器采用快速报错fail-fast机制,一旦检测到集合已被修改,抽象立即发出ConcurrentModificationException异常,而不是显示修改后的结果,这样可以避免在共享资源时而引发异常问题。
三、用foreach循环遍历集合
除了可以使用Iterator接口迭代访问Collection集合里元素之外,使用Java5提供的foreach循环迭代访问更简单。
Collection names = new HashSet();
names.add("张三");
names.add("李四");
for(Objection obj : names){
String name = (String)obj;
System.out.println(name);
}
与Iterator接口迭代集合元素类似,foreach循环中的迭代变量也不是集合元素本身,系统只是把值赋给变量,同样集合也不能改变。
使用Lambda表达式遍历Iterator
Java8为Iterator新增forEachRemaining()方法,该方法所需参数同样也是函数式接口,原理类似,调用时将集合元素传给Consumer的accept(T t)方法。
Collection names = new HashSet();
names.add("张三");
names.add("李四");
Iterator it = names.iterator();
it.forEachRemaining(obj -> System.out.println(" "+obj));

本质上还是遍历集合names,所有上面的方法也可以归为遍历集合方法的一种,利用Iterator的forEachRemaining方法和Lambda表达式遍历,又比Iterator自己提供的方法遍历简洁了一点。
最近优化了站点留言,欢迎访问主站点!