1.集合
Java集合类存放于 java.util 包中,是一个用来存放对象的容器。
集合类(除了 map 系列集合)都实现了 Iterator 接口,这是一个用于遍历集合中元素的接口,主要有hashNext(),next(),remove()三种方法。
- Object next():返回迭代器刚越过的元素的引用,返回值是 Object,需要强制转换成自己需要的类型
- boolean hasNext():判断容器内是否还有可供访问的元素
- void remove():删除迭代器刚越过的元素
Iterator是Java集合顶层接口,Map 是 map 系列集合顶层接口。
Iterator 接口在遍历集合中元素时,只能往后遍历,被遍历后的元素不会再被遍历到,通常无序集合实现是这个接口。元素有序的集合,实现的一般都是ListIterator 接口,实现这个接口的集合可以双向遍历。
2.Collection
单列集合,List 、Set 接口的父接口。
Collection 接口继承类 Iterable,它里面封装了 Iterator 接口。故只要实现了Iterable接口的类,就可以使用Iterator迭代器了。
Iterable :存在于 java.lang 包中; Iterator :存在于 java.util 包中。
public interface Collection<E> extends Iterable<E> {}public interface Iterable<T> {/*** @return an Iterator.*/Iterator<T> iterator();}
接口方法
| 接口声明 | 描述 |
|---|---|
| int size(); | 返回集合有多少个元素 |
| boolean isEmpty(); | 返回集合是否为空 |
| boolean contains(Object o); | 返回集合是否包含 o 元素 |
| boolean add(E e); | 给集合新增元素 e |
| boolean remove(Object o); | 删除集合中的 o 元素 |
| boolean containsAll(Collection<?> c); | 判断集合是否包含集合 c 中的元素 |
| boolean addAll(Collection<? extends E> c); | 向集合中新增集合 c 中的元素 |
| boolean removeAll(Collection<?> c); | 删除集合中与集合 c 中相同的元素 |
| Object[] toArray(); | 将集合转成数组 |
//遍历方式:迭代器、增强for
//Iterator-迭代器
Collection<String> list = new ArrayList<>();
// 添加元素略
Iterator iterator = list.iterator();
while (iterator.hasNext) {
System.out.println(iterator.next());
}
//增强 for 实际上底层也是使用 Iterator-迭代器 实现的遍历。相当于简化版的迭代器遍历
Collection<String> list = new ArrayList<>();
// 添加元素略
for (String str : list) {
System.out.println(str);
}
6.Properties
- Properties 继承自 HashTable
- Properties 更多地用于读取 .properties 配置文件
7.Comparator与Comparable
- Comparable & Comparator 都是用来实现集合中元素的比较、排序的,Comparable 是在集合内部定义的方法实现的排序,Comparator 是在集合外部实现的排序
- Comparator位于包java.util下,而Comparable位于包 java.lang下
- Comparable 是一个对象本身就已经支持自比较所需要实现的接口(如 String、Integer 自己就可以完成比较大小操作,已经实现了Comparable接口) 自定义的类要在加入list容器中后能够排序,可以实现Comparable接口,在用Collections类的sort方法排序时,如果不指定Comparator,那么就以自然顺序排序, 这里的自然顺序就是实现Comparable接口设定的排序方式。
- 而 Comparator 是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较
- 可以说一个是自已完成比较,一个是外部程序实现比较的差别而已。 用 Comparator 是策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。 比如:你想对整数采用绝对值大小来排序,Integer 是不符合要求的,你不需要去修改 Integer 类(实际上你也不能这么做)去改变它的排序行为,只要使用一个实现了 Comparator 接口的对象来实现控制它的排序就行了
8.集合类整体比较
9.Queue接口
继承了 Collection 接口,队列,先进先出
public interface Queue<E> extends Collection<E> {}
接口方法
| 方法声明 | 方法描述 |
|---|---|
| boolean add(E e); | 增加一个元素,如果队列已满,则抛出一个IIIegaISlabEepeplian异常 |
| boolean offer(E e); | 添加一个元素并返回true,如果队列已满,则返回false |
| E remove(); | 移除并返回队列头部的元素,如果队列为空,则抛出一个NoSuchElementException异常 |
| E poll(); | 移除并返问队列头部的元素,如果队列为空,则返回null |
| E element(); | 返回队列头部的元素,如果队列为空,则抛出一个NoSuchElementException异常 |
| E peek(); | 返回队列头部的元素,如果队列为空,则返回null |
10.Collections
- Collections 是一个操作 Set、List、Map 等集合的工具类
- Collections 中提供了一系列静态方法对集合元素进行排序、查询、修改等操作
添加
| 方法声明 | 描述 |
|---|---|
| boolean addAll(Collection<? super T> c, T… elements) | 将所有指定的元素添加到指定的集合中; |
排序
| 方法声明 | 描述 |
|---|---|
| void reverse(List<?> list) | 反转 list 中的元素顺序; |
| void shuffle(List<?> list) | 对 list 元素进行随机排序; |
| void sort(List list) | 根据其元素的自然顺序将 list 按升序排序;(list中的所有元素必须实现Comparable接口) |
| void sort(List list, Comparator<? super T> c) | 根据由指定比较器引起的顺序对指定列表进行排序。 |
| void swap(List<?> list, int i, int j) | 交换 list 中 i 与 j 位置的元素 |
查找、替换
| 方法声明 | 描述 |
|---|---|
| T max(Collection<? extends T> coll) | 根据其元素的自然顺序返回给定集合的最大元素。 |
| T max(Collection<? extends T> coll, Comparator<? super T> comp) | 根据指定比较器引发的顺序,返回给定集合的最大元素。 |
| T min(Collection<? extends T> coll) | 根据其元素的自然顺序返回给定集合的最小元素。 |
| T min(Collection<? extends T> coll, Comparator<? super T> comp) | 根据指定比较器引发的顺序,返回给定集合的最小元素。 |
| int frequency(Collection<?> c, Object o) | 元素 o 在 集合 c 中出现的次数。 |
| void copy(List<? super T> dest, List<? extends T> src) | 将 src 中的元素复制到 desc 中。 操作之后,desc 中每个复制元素的索引将与 src 列表中其索引相同。desc 列表必须至少与 src 列表一样长。 如果更长,则desc 中的其余元素将不受影响。 |
| boolean replaceAll(List list, T oldVal, T newVal) | 用 newVal 替换列表 list 中的每个 oldVal |
ArrayList集合加入1万条数据,应该怎么提高效率
因为ArrayList的底层是数组实现,并且数组的默认值是10,如果插入10000条要不断的扩容,耗费时间,所以我们调用ArrayList的指定容量的构造器方法ArrayList(int size) 就可以实现不扩容,就提高了性能。
在 Java 7 中,ArrayList 的默认大小是 10 个元素,HashMap 的默认大小是16个元素(必须是2的幂)。
ArrayList扩容的本质就是计算出新的扩容数组的size后实例化,并将原有数组内容复制到新数组中去。
数组和 List转换
- List转换成为数组:调用ArrayList的toArray方法。
- 数组转换成为List:调用Arrays的asList方法。
ArrayList 和 LinkedList
- ArrayList是数组的数据结构,LinkedList是链表的数据结构。
- 随机访问的时候,ArrayList的效率比较高,因为LinkedList要移动指针,而ArrayList是基于索引(index)的数据结构,可以直接映射到。
- 插入、删除数据时,LinkedList的效率比较高,因为ArrayList要移动数据。
- LinkedList比ArrayList开销更大,因为LinkedList的节点除了存储数据,还需要存储引用
ArrayList 和 Vector
- Vector是线程安全的,ArrayList不是线程安全的。
- ArrayList在底层数组不够用时在原来的基础上扩展0.5倍,Vector是扩展1倍。
- Vector只要是关键性的操作,方法前面都加了synchronized关键字,来保证线程的安全性。
Array 和 ArrayList
- 定义一个 Array 时,必须指定数组的数据类型及数组长度,即数组中存放的元素个数固定并且类型相同。
- ArrayList 是动态数组,长度动态可变,会自动扩容。不使用泛型的时候,可以添加不同类型元素。
HashSet和TreeSet
- Hashset 的底层是由哈希表实现的,Treeset 底层是由红黑树实现的。
- HashSet中的元素没有顺序,TreeSet保存的元素有顺序性(实现Comparable接口)
- HashSet的add(),remove(),contains()方法的时间复杂度是O(1);TreeSet中,add(),remove(),contains()方法的时间复杂度是O(logn)
HashMap 和 Hashtable ConcurrentHashMap
- HashMap
- 底层由链表+数组+红黑树实现
- 可以存储null键和null值
- 线性不安全
- 初始容量为16,扩容每次都是2的n次幂
- 加载因子为0.75,当Map中元素总数超过Entry数组的0.75,触发扩容操作.
- 并发情况下,HashMap进行put操作会引起死循环,导致CPU利用率接近100%
- HashMap是对Map接口的实现
HashTable
- HashTable的底层也是由链表+数组+红黑树实现。
- 无论key还是value都不能为null
- 它是线性安全的,使用了synchronized关键字。
- HashTable实现了Map接口和Dictionary抽象类
- Hashtable初始容量为11
ConcurrentHashMap
- ConcurrentHashMap的底层是数组+链表+红黑树
- 不能存储null键和值
- ConcurrentHashMap是线程安全的
- ConcurrentHashMap使用锁分段技术确保线性安全
JDK8为何又放弃分段锁,是因为多个分段锁浪费内存空间,竞争同一个锁的概率非常小,分段锁反而会造成效率低。
List 和 Set,Map
List 以索引来存取元素,有序,元素是允许重复的,可以插入多个null
- Set 不能存放重复元素,无序,只允许一个null
- Map 保存键值对映射,映射关系可以一对一、多对一
- List 有基于数组、链表实现两种方式
- Set、Map 容器有基于哈希存储和红黑树两种方式实现
- Set 基于 Map 实现,Set 里的元素值是 Map的键值
Collection与Collections
- Collection是Java集合框架中的基本接口,如List接口也是继承于它
public interface List<E> extends Collection<E> {
- Collections是Java集合框架提供的一个工具类,其中包含了大量用于操作或返回集合的静态方法。如下:
public static <T extends Comparable<? super T>> void sort(List<T> list) {
list.sort(null);
}
Collections.sort和Arrays.sort
Collection.sort是对list进行排序,Arrays.sort是对数组进行排序。
Collections.sort底层实现
Collections.sort方法调用了list.sort方法 list.sort方法调用了Arrays.sort的方法 ,因此,Collections.sort方法底层就是调用的Array.sort方法
Arrays.sort底层实现
Arrays的sort方法,如下:如果比较器为null,进入sort(a)方法。如下:因此,Arrays的sort方法底层就是:
- legacyMergeSort(a),归并排序,
- ComparableTimSort.sort():即Timsort排序。
Timesort排序
Timsort排序是结合了合并排序(merge.sort)和插入排序(insertion sort)而得出的排序方法;
1.当数组长度小于某个值,采用的是二分插入排序算法,如下:
- 找到各个run,并入栈。
- 按规则合并run。
迭代器
迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。
使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
使用next()获得序列中的下一个元素。
使用hasNext()检查序列中是否还有元素。
使用remove()将迭代器新返回的元素删除。
public interface Collection<E> extends Iterable<E> {
Iterator<E> iterator();
方法如下:
next() 方法获得集合中的下一个元素
hasNext() 检查集合中是否还有元素
remove() 方法将迭代器新返回的元素删除
forEachRemaining(Consumer<? super E> action) 方法,遍历所有元素
Iterator 主要是用来遍历集合用的,它的特点是更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛出 ConcurrentModificationException 异常。
使用demo如下:
List<String> list = new ArrayList<>();
Iterator<String> it = list. iterator();
while(it. hasNext()){
String obj = it. next();
System. out. println(obj);
}
Iterator 和 ListIterator
- ListIterator 比 Iterator有更多的方法。
- ListIterator只能用于遍历List及其子类,Iterator可用来遍历所有集合,
- ListIterator遍历可以是逆向的,因为有previous()和hasPrevious()方法,而Iterator不可以。
- ListIterator有add()方法,可以向List添加对象,而Iterator却不能。
- ListIterator可以定位当前的索引位置,因为有nextIndex()和previousIndex()方法,而Iterator不可以。
- ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改哦。
Enumeration和Iterator接口
public interface Enumeration<E> {
boolean hasMoreElements();
E nextElement();
}
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}
- 函数接口不同
- Enumeration速度快,占用内存少,但是不是快速失败的,线程不安全。
- Iterator允许删除底层数据,枚举不允许
- Iterator安全性高,因为其他线程不能够修改正在被Iterator遍历的集合里面的对象。
参考
HashMap集合(高级)
Map 综述(一):彻头彻尾理解 HashMap
