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 包中。

  1. public interface Collection<E> extends Iterable<E> {}
  2. public interface Iterable<T> {
  3. /**
  4. * @return an Iterator.
  5. */
  6. Iterator<T> iterator();
  7. }

接口方法

接口声明 描述
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.当数组长度小于某个值,采用的是二分插入排序算法,如下:

  1. 找到各个run,并入栈。
  2. 按规则合并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();
}