1、集合概述

存储对象的容器

集合与数组的区别

  • 存储类型
    数组:可以存储任意类型数据,基本数据类型、引用数据类型
    集合:只能存储引用类型,基本数据类型存储时自动装箱
  • 容量
    数组:定长,创建后不可更改
    集合:变长,随存储元素的数量动态改变

Java中集合框架结构

Java respose获取print内容_数组

集合框架的好处

  1. 容量自增长;
  2. 提供了高性能的数据结构和算法,使编码更轻松,提高了程序速度和质量;
  3. 可以方便地扩展或改写集合,提高代码复用性和可操作性。
  4. 通过使用JDK自带的集合类,可以降低代码维护和学习成本。

2、Iterator接口

Iterator接口,用于遍历集合元素的接口。

在Iterator接口中定义了三个方法

boolean	hasNext() //如果仍有元素可以迭代,则返回true。
E next() //返回迭代的下一个元素,同时移向该元素后一个元素(正向)。
void remove() //从迭代器指向的 collection 中移除迭代器返回的最后一个元素。

每一个集合都有自己的数据结构(容器中存储数据的方式),因此取出元素的方式各不相同。为了便于操作所有的容器,取出元素。JDk提供Iterator接口,使得对容器的遍历操作与其具体的底层实现相隔离,达到解耦的效果。

2.1 迭代器Iterator获取元素

使用方法:

//step1 对要遍历的集合对象,使用.iterator()方法获取迭代器对象
Iterrator<E> it = 集合对象.iterator();
//step2 判断迭代器是否还有元素
while(it.hasNext()) {
    //step3 获取元素
    it.next();
}
  • 迭代器获取元素时,需要先判断是否还存在元素。否则可能抛出NoSuchElementException异常
  • 迭代器工作期间,集合本身不能修改自己的结构,否则会出现意外,安全的删除方法使用接口中的remove()方法

2.1 ListIterator接口

是一个功能更加强大的迭代器, 它继承于Iterator接口,只能用于各种List类型的访问。

通过调用listIterator()方法产生一个指向List开始处的ListIterator对象, 还可以调用listIterator(n)方法创建一个一开始就指向列表索引为n的元素处的ListIterator对象。

特点

  • 可以向前、向后两个方向遍历 List;
  • 在遍历时可以修改 List 中的元素;
  • 遍历时可以获取迭代器当前游标所在位置。

常用方法

//除继承Iterator接口中的方法,还新增以下方法
boolean	hasPrevious() //反向遍历集合时判断其前方是否还有元素
int	nextIndex() //返回调用 next()后返回的元素索引。
E previous() //反向遍历时,获取集合上一个元素,同时光标向前移动。
int	previousIndex() //返回调用previous() 后返回的元素索引 。
void remove() //删除列表中调用next()或previous()的返回最后一个元素。
void set(E e) //用指定元素替换列表中调用next()或previous()的返回最后一个元素。

3 Collection接口

Collection一次存一个元素,是单列集合的根接口

Collection集合主要有List和Set两大接口

  • List:有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素可以重复。
  • Set:无序(存入和取出顺序有可能不一致),不可以存储重复元素。必须保证元素唯一性。

主要方法

boolean add(E e)  //添加元素
boolean remove(Object o) //从该集合中删除指定元素(如果存在)
int size() //返回此集合中的元素个数。 
boolean contains(Object o)  //集合中是否包含指定元素
void clear()  //清空集合中元素
Iterator<E> iterator() //集合中的元素的迭代器。  
    
//其他方法
boolean addAll(Collection<? extends E> c) //将指定集合中的所有元素添加到此集合 
boolean removeAll(Collection<?> c) //删除集合中指定集合中的所有元素 底层使用equals方式比较
boolean isEmpty()  //判定集合中是否含有元素
boolean retainAll(Collection<?> c) //仅保留集合中指定集合中的所有元素 底层使用equals方式比较

4、List接口

List是元素有序(存在下标)且允许元素重复的集合,Collection的一个字接口

List的主要实现类 – ArrayList 、 linkedList、Vector

继承结构

Java respose获取print内容_数组_02

主要方法

//除继承自collection中方法外,新增加方法均与下标相关
void add(int index, E element) // 在指定位置插入元素
boolean addAll(int index, Collection<? extends E> c) //在指定位置插入集合中所有元素
E remove(int index) //删除指定位置的元素 
E set(int index, E element)  //将指定位置的元素替换为目标元素
E get(int index)  //获取指定位置元素
List<E> subList(int fromIndex, int toIndex)  //获取[formIndex,toIndex)间的元素子集合
int indexOf(Object o) //返回集合指定元素的第一次出现的索引,如果集合不包含该元素,则返回-1。

遍历元素方法

  • for-each,增强for循环
  • Iterator迭代器
  • 普通for循环,结合get(index)方法

4.1 ArrayList实现类

是List的一个实现类,底层使用数组实现,相当于一个动态数组

Java respose获取print内容_数组_03

它还实现了三个标识型接口,这几个接口都没有任何方法,仅作为标识表示实现类具备某项功能。RandomAccess表示实现类支持快速随机访问,Cloneable表示实现类支持克隆,Serializable则表示支持序列化。

特点

  • 基于数组实现
  • 可以动态调整容量
  • 有序且元素允许重复,元素可以为null
  • 不同步,线程不安全,效率高
  • 查询快,增删慢
  • 对比LinkedList占用空间更小

常用方法

直接实现List接口中的方法,无新增。同List常用方法

4.2 LinkedList实现类

List的一个实现类,基于双向链表实现

继承关系

Java respose获取print内容_java_04

LinkedList,同时又实现了 List 和 Deque(双端队列 Double-End Queue) 接口中的方法

特点

  • 基于双向链表实现
  • 有序,允许null与重复值
  • 不同步,线程不安全,效率高
  • 由于LinkedLIst需要额外存储元素前驱与后继的引用,相对ArrayList更占空间

主要方法

//除继承自List集合的中的方法外,还新增的有
//模拟栈结构
void push(E e) // 将元素推送到由此集合表示的堆栈上(入栈)。  
E pop() // 从此集合表示的堆栈中弹出一个元素(出栈)。  

//模拟队列结构
boolean offer(E e) // 将指定的元素添加为此集合的尾部(入列)。  
E poll() // 获取并删除此集合的头元素(出列)。  
    
//其他操作
void addFirst(E e) //在该集合开头插入指定的元素。 
void addLast(E e) //将指定的元素追加到此集合的末尾。  
E element() //获取但不删除此集合的元素 
E getFirst() //返回此集合中的第一个元素。  
E getLast() //返回此集合中的最后一个元素。 
E peek() //获取但不删除此集合的头元素。  
E peekFirst() //获取但不删除此集合的第一个元素,如果此集合为空,则返回 null 。  
E peekLast() //获取但不删除此集合的最后一个元素,如果此集合为空,则返回 null 。

4.3 Vector实现类(已过时)

List的一个实现类,底层由数组实现。已过时被ArrayList替代

方法同ArrayList中方法。

迭代元素时,还可以使用elements()获取Enumeration对象

  • hasMoreElements() 同 hasNext()
  • nextElement() 同 next()

4.4 ArrayList、LinkedList、Vector比较

ArrayList

LinkedList

Vector

底层实现

数组

双向链表

数组

同步性及效率

不同步,非线程安全,效率高,支持随机访问

不同步,非线程安全,效率高

同步,线程安全,效率低

特点

查询快,增删慢

查询慢,增删快

查询快,增删慢

默认容量

10

/

10

扩容机制

int newCapacity = oldCapacity + (oldCapacity >> 1);//1.5 倍

/

2 倍

5、Set接口

Collection子接口 元素无序,且不能重复

常用方法:继承自Collection中的方法,无新增

5.1 HashSet实现类

Set接口的实现类,底层是HashMap的一个实例,元素无序、不能重复

去重方法:使用元素的HashCode()与equals()方法,需要重写两个方法

常用方法:Collection中的常用方法

5.1.1 LinkedHashSet实现类

HashSet的一个子类,底层是LinkedHashMap的一个实例。保证了元素可预测迭代顺序(存入顺序),且元素去重

常用方法:Collection中的常用方法

5.2 比较器

5.2.1 Comparable接口

标记该类的实例可以实现自然排序,排序依据为调用compareTo()方法

java.lang.Comparable使用方法

//元素对象所属类实现了Comparable接口
class Person implements Comparable {
    @override
    int compareTo(T o) //将此对象与指定的对象进行比较以进行排序。
}

排序规则(根据返回值)

  • 正数 :this > o 将this排在o之后
  • 负数:this < o 将this排在o之前
  • 零: this = o this与o相同,去重依据
5.2.2 Comparator接口

自定义比较器接口,用以对象的排序

java.util.Comparator使用方法

class Person {}
//创建接口的实现类
class PersonCompara implements Comparator {
    //实现比较方法
    int compara(T o1, T o2) {}
}
//new集合时传入的接口实现类
TreeSet<Person> set = new TreeSet<>(PersonCompara);

//创建集合时,直接使用匿名内部类
TreeSet<Person> set = new TreeSet<>(new Comparator() {
    //实现比较方法
    int compara(T o1, T o2) {}
});

排序规则(根据返回值)

  • 正数:o1 > o2 o1排在o2后面
  • 负数:o1 < o2 o1排在o2前面
  • 零:o1 = o2 o1与o2相同,去重依据

5.3 TreeSet实现类

Set接口的一个实现类,同时还实现了SortedSet接口。底层是TreeMap的一个实例,元素有序(自然排序或者定制排序),无重复元素

去重方法:元素已经实现Comparable接口自然排序去重或者集合创建时传入Comparator接口实现类定制排序去重

常用方法

//继承自Set接口中的方法,即Collection中方法
E ceiling(E e) //返回此集合中大于或等于给定元素的最小元素,如果没有此元素,则返回 null。例如集合[aaa,bbb,ccc,ddd] ceiling("bbc") --> ccc
E floor(E e) //返回此集合中小于或等于给定元素的最大元素,如果没有这样的元素,则返回 null。例如集合[aaa,bbb,ccc,ddd] floor("bbc") --> bbb
E higher(E e) //返回大于给定元素的该集合中的最小元素,如果没有此元素则返回 null  例如集合[aaa,bbb,ccc,ddd] higher("ccc") --> ddd
E lower(E e) //返回这个集合中最大的元素严格小于给定的元素,如果没有这样的元素,则返回 null 。 例如集合[aaa,bbb,ccc,ddd] lower("ccc") --> bbb 
E first() //返回此集合中排序第一个元素。  
E last() //返回此集合中排序最后一个元素。  
SortedSet<E> headSet(E toElement) //小于toElement的部分集合 。 例如集合[aaa,bbb,ccc,ddd] headSet("ccc") --> [aaa,bbb]
NavigableSet<E> tailSet(E fromElement)  //大于或等于fromElement的部分集合。 例如集合[aaa,bbb,ccc,ddd] tailSet("ccc") --> [ccc,ddd]
SortedSet<E> subSet(E fromElement, E toElement) //获取[fromElement, toElement)间的子集合

5.4 HashSet、TreeSet、LinkedHashSet比较

HashSet

TreeSet

LinkedHashSet

底层实现

HashMap

TreeMap

LinkedHashMap

元素重复性

不允许重复

不允许重复

不允许重复

元素有无序

无序

有序,支持两种排序方式,自然排序和定制排序,其中自然排序为默认的排序方式。

有序,即元素插入的顺序

同步性

不同步,线程不安全

不同步,线程不安全

不同步,线程不安全

null值

允许null值

不支持null值,会抛出 java.lang.NullPointerException 异常

允许null值

去重方法

HashCode()、equals()

compareTo()与compare()

HashCode()、equals()

6、Map接口

Map是一种把键对象和值对象映射的集合。是双列集合(一次存储两个数据)

Map中的元素,总是成对存在。分为键(K Key)与值(V Value),他们是映射关系。

继承结构

Java respose获取print内容_面试_05

特点

  • 键(k)不允许重复,当存入数据键重复时,新值覆盖旧值
  • 值(V)允许重复

常用方法

//增
V put(K key, V value) //将指定的键值对存入Map。V 被替换的值 没有替换返回null
void putAll(Map<? extends K,? extends V> m)  //存入Map对象

//删
V remove(Object key)  //删除指定键的键值对映射
void clear() // 从该Map中删除所有的映射 

//获取
int size() //返回此Map中键值映射的数量。  
V get(Object key) //获取指定键所映射的值,不存在返回null
Set<K> keySet() // 获取此Map中包含的所有键的Set集合。  
Set<Map.Entry<K,V>> entrySet()  // 获取Map中包含的所有键值映射的Set集合。 
Collection<V> values() //获取Map包含的所有值的Collection集合。  

//判断
boolean isEmpty()  // 判断集合是否为空
boolean containsKey(Object key) //判断Map中是否含有指定键 
boolean containsValue(Object value)  //判断Map中是否含有指定值

6.1 Map.Entry

定义在Map接口中的一个内部接口,他表示一个映射项(包含有Map中的key与value)

Map接口中的entrySet()返回一个包含有Entry类型元素的Set集合,通过Entry中的方法getKey()与getValue()方法,即能遍历出Map中的每一个键值对值

使用方法

//1. 获取Set(Map.Entry<K,v>)集合
Set<Entry<String, String>> set = map.entrySet();
//2. 遍历Set集合,获取Entry对象
Entry<String, String> entry = set.iterator();
//3. 获取键值
entry.getKey();
entry.getValue();

6.2 HashMap实现类

Map的一个实现类,基于哈希表实现(JDk1.7为数组链表,JDK1.8为数组链表加红黑树)

继承结构

Java respose获取print内容_数组_06

HashMap继承抽象类AbstractMap,实现Map接口

Key去重原理同HashSet去重

常用方法:实现的Map中方法

6.2.1 HashMap在JDk1.7与1.8区别

不同

JDk1.7

JDk1.8

存储结构

数组 + 链表

数组 + 链表 + 红黑树

初始化方式

单独函数:inflateTable()

集成到扩容函数resize()

hash值计算方式

扰动处理 :9次扰动 (4次位运算 + 5次异或运算)

扰动处理 :2次扰动(1次位运算 + 1次异或运算)

存放数据的规则

无冲突时,存放数组;冲突时,存放链表

无冲突时,存放数组;冲突 & 链表长度 < 8:存放单链表;冲突 & 链表长度 > 8:树化并存放红黑树

插入数据方式

头插法(先将原位置的数据后移1位,再插入数据到该位置)

尾插法(直接插入到链表尾部/红黑树)

6.2.2 LinkedHashMap实现类

HashMap的子类,基于链表和哈希表实现。可以保证元素的存入顺序

去重原理:同HashMap(使用元素的HashCode()与equals()方法)

常用方法:同HashMap

6.3 Hashtable实现类(已过时)

Map的实现类,底层基于哈希表实现。已过时被HashMap代替

HashMap与Hashtable比较

  • 都是Map的实现类(HashMap代替Hashtable)
  • HashMap继承自AbstractMap,Hashtable继承自Dictionary
  • Hashtable同步、线程安全。HashMap不同步,线程不安全
  • HashMap允许存入null值,Hashtable不允许存入null值
6.3.1 Properties类

Hashtable的一个子类,表示一个持久的属性集

主要用于存储一些配置信息,可以从流中加载、也可以保存到流中,泛型K与V均为String类型

常用方法

String getProperty(String key) //使用此属性集合中指定的键搜索属性。  
Object setProperty(String key, String value) //同 Hashtable方法 put 。  
void load(InputStream inStream) //从输入字节流读取属性集合(键值对)。
void load(Reader reader) //以简单的线性格式从输入字符流读取属性集合(键值对)。
void store(OutputStream out, String comments) //使用字节输出流将此属性集合(键值对)保存
void store(Writer writer, String comments) //使用字符输出流将此属性集合(键值对)保存

6.4 TreeMap实现类

Map的实现类,基于黑红树实现,K有序(排序)

继承结构

Java respose获取print内容_数组_07

TreeMap继承于AbstractMap,直接实现NavigableMap

去重方法(排序方式):元素已经实现Comparable接口自然排序去重或者集合创建时传入Comparator接口实现类定制排序去重

常用方法

//除继承自Map中的方法还有如下
K ceilingKey(K key) //返回TreeMap中大于或等于指定Key的最小Key值,如果没有返回 null 。 
K floorKey(K key) //返回TreeMap中小于或等于给定Key的最大key值,如果没有返回null 。 
K firstKey()  //返回TreeMap中第一个键。
K lastKey() //返回TreeMap中最后一个键。  
SortedMap<K,V> headMap(K toKey) //返回key小于toKey值得子Map集合。  
SortedMap<K,V> tailMap(K fromKey) //返回key大于等于 fromKey值的子Map集合 。

6.5 HashMap、Hashtable、TreeMap比较

HashMap

Hashtable

TreeMap

底层实现

哈希表(数组+链表)

哈希表(数组+链表)

红黑树

线程安全性

不安全

安全

不安全

null值

允许key与value为null,且只允许一个key为null

不允许key、value 是 null

value允许为null。

元素hash值

使用hash(Object key)扰动函数对 key 的 hashCode 进行扰动后作为 hash 值

直接使用 key 的 hashCode() 返回值作为 hash 值

/

容量

默认容量为 16 且容量一定是 2^n

默认容量是11,不一定是 2^n

/

扩容

两倍

2n+1倍

/

7、泛型

类型参数化,在定义时不使用具体类型限定,创建时才限定类型。类似于方法中的参数,提高代码的复用性(JDk1.5)

7.1 泛型类

声明的时候使用<>,做限制类型,类中只能存在普通方法与属性。泛型接口使用类基本相同

class 类名<T> {
    // T  type
    // E  element
    //K   key
    //V   value
}

泛型擦除:使用时没有指明泛型具体的类型,则类型自动变为Object类型

7.2 泛型静态方法

静态方法需要使用泛型时,需要在方法声明时同时独立声明泛型,声明泛型应写在static关键字之后,返回类型值之前

//静态方法独立声明泛型,不能使用类声明泛型
public static <T> T test(T t) {
    return t;
}

7.3 泛型限定

  • ?:代表可以使用任意类型
  • ? extends T:限定上限。可以使用T及T的子类
  • ? super T:限定下限。可以使用T及T的父类

7.4 不允许使用泛型的地方

  1. 静态的属性
  2. 创建泛型的实例。 例如:T t = new T()
  3. 自定义异常时,不能使用泛型

8 Collections工具类

提供集合的常用静态操作方法

//获取线程安全的集合
static <T> Collection<T> synchronizedCollection(Collection<T> c) //返回由指定集合支持的同步(线程安全)集合。  
static <T> List<T> synchronizedList(List<T> list) //返回由指定List支持的同步(线程安全)List。  
static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) //返回由指定Map支持的同步(线程安全)Map。  

//向Collection容器中添加元素
static <T> boolean addAll(Collection<? super T> c, T... elements) //将所有指定的元素添加到指定的集合。
    
//对于List操作
//使用二叉搜索算法搜索指定对象的指定列表。 
static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) 
//使用二叉搜索算法搜索指定对象的指定列表。  
static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c)   
static <T extends Comparable<? super T>> void sort(List<T> list) //对List元素进行自然排序。 
static <T> void sort(List<T> list, Comparator<? super T> c) //根据指定的比较器对指定的List进行排序。  
static void reverse(List<?> list)  // 反转指定列表中元素的顺序。 
static void shuffle(List<?> list) // 使用默认的随机源随机排列指定的列表。  
static <T> boolean replaceAll(List<T> list, T oldVal, T newVal) //将列表中一个指定值的所有出现替换为另一个。  
static int frequency(Collection<?> c, Object o) //返回指定集合中与指定对象相等的元素数。