Java最初版本只为最常用的数据结构提供了很少的一组类Vector、Stack、HashTable、BitSet和Enumeration接口,其中Enumeration接口提供了一种用于访问任意容器中各个元素的抽象机制.
集合框架的基本设计:将接口(interfaces)与实现(implementations)分离.
数据结构一队列
队列是指可以在队列的尾部添加元素,在队列的头部删除元素,并且可以 查找队列中元素的个数,按照先进先出的规则检索对象.
队列有两种实现方式,一种是循环组数,一种是链表.循环组数比链表更高效,但循环组数是一个有界集合,即容量有限,如果程序中要收集的对象数量没有上限,最好用链表来实现.
Collection接口:
集合类的基本接口是Collection接口,是集合层次中的根接口.下面先看下Collection接口中的方法:
- int size(); 返回当前集合的元素个数
- boolean isEmpty(); 判断集合是否为空,为空返回true
- boolean contains(Object o); 如果此集合包含指定的元素,则返回true
- Iterator iterator(); 返回此集合中元素的迭代器,用于访问集合中的每一个元素
- Object[] toArray(); 返回包含此集合中所有元素的数组。
- T[] toArray(T[] a); 返回包含此集合中所有元素的数组;如果T足够大,就将集合中的元素添加到此数组,剩余空间填补null,否则分配一个新数组,类型与T一直,数组长度等于集合大小,填充集合元素
- boolean add(E e); 将元素添加到集合中,成功返回true
- boolean remove(Object o); 从集合中删除匹配到对象o的元素,删除成功返回true
- boolean containsAll(Collection<?> c); 如果集合包含指定集合的所有元素,返回true
- boolean addAll(Collection<? extends E> c); 将指定集合中的所有元素添加到此集合
- boolean removeAll(Collection<?> c); 移除方法中还包含此集合的所有元素
- default boolean removeIf(Predicate<? super E> filter) 移除此集合中满足给定条件的所有元素
- boolean retainAll(Collection<?> c); 仅保留此集合中包含的元素
- void clear(); 从该集合中删除所有元素
- boolean equals(Object o); 将指定的对象与此集合进行相等性比较
- int hashCode(); 返回此集合的哈希码
1.8 - default Spliterator spliterator() 在此集合上创建一个spliterator迭代器
1.8 - default Stream stream() 返回该集合的流
1.8 - default Stream parallelStream() 返回一个可能与此集合并行的流,该方法允许返回顺序流
add()方法用于添加元素,添加成功集合元素改变返回true,若是添加的元素在集合中已经存在,集合元素没有发生改变,则返回false,因为集合中不允许重复.iterator()方法用于返回一个实现了Iterator接口的对象.可以使用这个迭代去对象一次访问集合中的元素.
迭代器:
Iterator接口中包含四个方法,如下:
- boolean hasNext(); 如果存在可访问元素返回true
- E next(); 返回将要访问的下一个对象.如果到达集合尾部,会抛出NoSuchElementException
- default void remove()删除上次访问对象.正则方法必须跟在访问一个元素之后执行,否则将抛出IllegelStateException
- default void forEachRemaining(Consumer<? super E> action) 为每个剩余元素执行给定的操作,直到所有元素已处理或操作引发异常
通过反复调用next()方法,可以依次访问集合中的每个元素,但是如果到达集合的末尾.next()将抛出一个NoSuchElementException异常,因此,需要在调用next()方法之前调用hasNext()方法,如果还有课供访问的元素,就返回true,若要查看一个集合的所有元素,就请求一个迭代器,在hashNext()方法饭后true时反复调用next()方法.
示例一:
不调用hasNext()方法
class Test{
public static void main(String[] args) {
Collection<String> stringCollection = new ArrayList<>();
Collection<String> collection = new ArrayList<>();
collection.add("aaa");
collection.add("bbb");
collection.add("ccc");
stringCollection.add("ddd");
stringCollection.add("eee");
stringCollection.add("fff");
collection.addAll(stringCollection);
Iterator iterator = collection.iterator();
while (collection.size()>0){
Object o = iterator.next();
System.out.println(o);
}
}
}
运行结果
示例二:
调用hasNext()方法
class Test{
public static void main(String[] args) {
Collection<String> stringCollection = new ArrayList<>();
Collection<String> collection = new ArrayList<>();
collection.add("aaa");
collection.add("bbb");
collection.add("ccc");
stringCollection.add("ddd");
stringCollection.add("eee");
stringCollection.add("fff");
collection.addAll(stringCollection);
Iterator iterator = collection.iterator();
while (iterator.hasNext()){
Object o = iterator.next();
System.out.println(o);
}
}
}
运行结果
也可以用for each循环进行更加简便的操作,Collection接口实现了Iterable接口,for each循环可以同任何实现了Iterable接口的对象一起工作,在1.8之前1.5之后Iterable接口只包含了一个方法.在1.8新增了两个方法
- Iterator iterator(); 此接口允许对象成为for each循环的目标
1.8 - default void forEach(Consumer<? super T> action) 遍历所有元素,直到查出所有元素或抛出异常
1.8 - default Spliterator spliterator() 创建一个spliterator迭代器
在Java1.8中,可以不写循环,直接调用forEachRemaining()方法,并提供一个lambda表达式(处理一个元素),迭代器的每一个元素都调用这个lambda表达式,直到没有元素为止.用上面的for each的例子稍微修改如下:
class Test{
public static void main(String[] args) {
Collection<String> stringCollection = new ArrayList<>();
Collection<String> collection = new ArrayList<>();
collection.add("aaa");
collection.add("bbb");
collection.add("ccc");
stringCollection.add("ddd");
stringCollection.add("eee");
stringCollection.add("fff");
collection.addAll(stringCollection);
Iterator iterator = collection.iterator();
iterator.forEachRemaining(String -> System.out.println(String));
}
}
运行结果
元素被访问的顺序取决于集合类型,如果对ArrayList进行迭代,迭代器将从索引0开始,没迭代一次,索引值加1,如果是访问HashSet中的元素,每个元素会按照某种随机的次序出现,可以遍历所有元素,但无法预知元素被访问的顺序.
Iterator接口的remove()方法会删除上次调用next()方法是返回的元素,在调用remove()方法之前必须先调用next()方法,如果不调用next()方法直接调用remove方法,会抛出IllegalStateException异常.next()方法与remove()方法具有相互依赖性.
示例一:
直接调用remove()方法
class Test{
public static void main(String[] args) {
Collection<String> stringCollection = new ArrayList<>();
Collection<String> collection = new ArrayList<>();
collection.add("aaa");
collection.add("bbb");
collection.add("ccc");
stringCollection.add("ddd");
stringCollection.add("eee");
stringCollection.add("fff");
collection.addAll(stringCollection);
Iterator iterator = collection.iterator();
iterator.remove();
}
}
运行结果
示例二:
先调用next()方法后调用remove()方法
public static void main(String[] args) {
Collection<String> stringCollection = new ArrayList<>();
Collection<String> collection = new ArrayList<>();
collection.add("aaa");
collection.add("bbb");
collection.add("ccc");
stringCollection.add("ddd");
stringCollection.add("eee");
stringCollection.add("fff");
collection.addAll(stringCollection);
Iterator iterator = collection.iterator();
iterator.next();
iterator.remove();
iterator.forEachRemaining(String -> System.out.println(String));
}
}
运行结果
删除下标为0的
Collection接口和Iterator接口都是泛型接口,可以编写操作任意类型的方法.
Java集合框架为不同类型的集合定义大量的接口,集合有两个基本接口:Collection和Map.
List是一个有序集合,元素会增加到容器的特定位置,可以采用laingzh两种方式访问元素,使用迭代器或者使用证书索引来访问,使用迭代器访问,必须是有序的访问,整数索引访问则可以随机任意顺序访问元素.
Set接口类似Collection接口,不过方法更加严谨,Set的add()方法不允许添加重复元素.
在这里可以引出一个经典的面试题
List和Set的区别:
List(列表):
- 有序
- 可重复
- 元素都有索引,可通过索引访问元素
Set(集): - 无序
- 不可重复
上面对集合的做了简单的介绍,其他的内容会在后面的博客再做介绍,若发现错误和不足之处,欢迎指正.