Java容器总结
文章总结自博客: https://blog.csdn.net/zhangqunshuai/article/details/80660974

概述
- List、Set、Map都是接口,前两个继承至Collection接口,Map为独立接口
- Set下有
HashSet、LinkedHashSet、TreeSet - List下有
ArrayList、Vector、LinkedList - Map下有
HashTable、LinkedHashMap、HashMap、TreeMap - Collection接口下还有个
Queue接口,有PriorityQueue类
Collection接口下面有三个接口List、Set、Queue
LinkedList既可以实现Queue接口,也可以实现List接口,但是当LinkedList实现Queue接口,Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时,就完全只能访问Queue接口所定义的方法了,而不是能直接访问LinkedList的非Queue的方法),以使得只有恰当的方法才可以使用SortedSet是个接口,它里面的(只有TreeSet这一个实现可用)中的元素一定是有序的
📚Collection
📒List
有序,可重复
📃ArrayList
优点:底层数据结构是数组,查询快,增删慢
缺点:线程不安全,效率高
📃Vector
优点:底层数据结构是数组,查询快,增删慢
缺点:线程安全,效率低
📃LinkedList
优点:底层数据结构是链表,查询慢,增删快
缺点:线程不安全,效率高
📒Set
无序,唯一
📃HashSet
底层数据结构是哈希表(无序,唯一)
如何保证元素唯一性?
1.依赖两个方法:hashCode()和equals()
📃LinkedHashSet
底层数据结构是链表和哈希表(有序,唯一)
- 由链表保证元素有序
- 由哈希表保证元素唯一
📃TreeSet
底层数据结构是红黑树(有序,唯一)
1.如何保证元素排序的呢?
- 自然排序
- 比较器排序
2.如何保证元素的唯一性的呢?
根据比较的返回值是否为0来决定
📃总结
TreeSet的主要功能用于排序LinkedHashSet的主要功能用于保证FIFO即有序的集合(先进先出)HashSet只是通用的存储数据的集合
📒使用场景
📃唯一:Set
- 排序:
TreeSet或LinkedHashSet - 不排:
HashSet - 知道是
Set,但是不知道是哪个,就用HashSet
📃不唯一:List
- 安全:Vector
- 不安全:
ArrayList或LinkedList- 查询多:
ArrayList - 增删多:
LinkedList - 如果知道是
List,但是不知道是哪个List,就用ArrayList
- 查询多:
📚Map
Map接口有三个比较重要的实现类,分别是HashMap、TreeMap、HashTable
TreeMap是有序的,HashMap和HashTable是无序的HashTable的方法是同步的,HashMap的方法不是同步的
这就意味着
HashTable是线程安全的,HashMap不是线程安全的HashMap效率高,Has和Table效率较低- 如果对同步性或与遗留代码的兼容性没有任何要求,建议使用
HashMap。 查看Hashtable的源代码就可以发现,除构造函数外,Hashtable的所有 public 方法声明中都有synchronized关键字,而HashMap的源码中则没有
- 如果对同步性或与遗留代码的兼容性没有任何要求,建议使用
HashTable不允许null值,HashMap允许null值(key和value都允许)- 父类不同:
HashTable的父类是Dictionary,HashMap的父类是AbstractMap
========================
Collection
Collection集合中通用的功能
Collection集合常用符方法
| 方法名 | 说明 |
|---|---|
| boolean add(E e) | 添加元素 |
| boolean remove(Object o) | 从集合中移除指定的元素 |
| void clear() | 清空集合中的元素 |
| boolean contains(Object o) | 判断集合中是否存在指定的元素 |
| boolean isEmpty() | 判断集合是否为空 |
| int size() | 集合的长度 |
package com.study_01;import java.util.ArrayList;import java.util.Collection;public class CollectionDemo02 {public static void main(String[] args) {// 通过多态的方法创建对象Collection<String> c = new ArrayList<>();// add方法永远返回true// System.out.println(c.add("hello")); // truec.add("hello");c.add("java");c.add("world");// 删除元素:boolean remove(Object o)// System.out.println(c.remove("world")); // true// System.out.println(c.remove("javaee")); // false// 清除集合中的元素:void clear()// c.clear();// 判断集合中是否存在指定的元素:boolean contains(Object o)// System.out.println(c.contains("world")); // true// System.out.println(c.contains("javaee")); // falseSystem.out.println(c.isEmpty()); // 判断集合是否为空System.out.println(c.size()); // 集合的长度System.out.println(c);}}
Collection集合的遍历
**lterator**:迭代器,集合的专用遍历方式
存在并发修改异常
Iterator iterator:返回此集合中元素的迭代器,通过集合的iterator()方法得到- 迭代器是通过集合的
iterator()方法得到的,所以我们说它是依赖于集合而存在的
**lterator**中的常用方法
E next():返回迭代中的下一个元素boolean hasNext():如果迭代具有更多元素,则返回true
增强for循环:简化数组和Collection集合的遍历
- 实现
lterable接口的类允许其对象成为增强型for语句的目标 - 它是JDK5之后出现的,其内部原理是一个
lterator迭代器
for(元素数据类型 变量名:数组或者Collection集合){//在此处使用变量即可,该变量就是元素}int[] arr = {1,2,3,4,5};// 内部其实是个Iterable迭代器for (int i :arr) {System.out.println(i);}
package com.study_02;import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;public class IteratorDemo {public static void main(String[] args) {// 创建Collection集合对象 多态Collection<String> c = new ArrayList<>();// 添加元素:boolean add(E e)c.add("hello");c.add("world");c.add("java");// Iterator<E> iterator() 返回此集合中元素的迭代器 通过集合的iterator()方法得到Iterator<String> it = c.iterator();/* ----Iterator<E> iterator()-----public Iterator<E> iterator() {return new Itr();}private class Itr implements Iterator<E> {...}*/// 用while循环改进判断// boolean hasNext():如果迭代具有更多元素,则返回truewhile (it.hasNext()) {// E next():返回迭代中的下一个元素String s = it.next();System.out.println( s);}}}
List集合特有的功能
List集合特有方法
| 方法名 | 说明 |
|---|---|
| void add(String item, int index) | 在此集合指定位置插入指定的元素 |
| E remove(int index) | 删除指定索引出的元素,返回别删除的元素 |
| E set(int index,E element) | 修改指定索引出的元素,返回被修改的元素 |
| E get(int index) | 返回指定索引处的元素 |
package com.study_01;import java.util.ArrayList;import java.util.List;public class ListDemo02 {public static void main(String[] args) {List<String> list = new ArrayList<>();// 添加元素:boolean add(E e)list.add("hello");list.add("world");list.add("java");// 在此集合指定位置插入指定的元素:void add(String item, int index)// list.add(1,"javaEE");// list.add(11,"javaEE"); // IndexOutOfBoundsException 索引越界异常// 删除指定索引处的元素,返回别删除的元素:E remove(int index)// System.out.println(list.remove(1)); // world// System.out.println(list.remove(11)); // IndexOutOfBoundsException 索引越界异常// 修改指定索引处的元素,返回被修改的元素:Eset(Int index,E element)// System.out.println(list.set(1,"javaEE")); // world// System.out.println(list.set(11,"javaEE")); // IndexOutOfBoundsException 索引越界异常// 返回指定索引处的元素:E get(int index)// System.out.println(list.get(1)); // world// System.out.println(list.get(11)); // IndexOutOfBoundsException 索引越界异常// System.out.println(list);for (int i = 0; i < list.size(); i++) {// E next():返回迭代中的下一个元素String s = list.get(i);System.out.println(s);} 34m}}
ListIterator列表迭代器
**Iterator**会引发的问题
并发修改异常:ConcurrentModificationException
产生原因:迭代器遍历的过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际修改值不一致‘’
**ListIterator**列表迭代器
- 通过List集合的listlterator()方法得到,所以说它是List集合特有的迭代器
- 用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置
**ListIterator**中常用的方法
| 方法名 | 说明 |
|---|---|
| E next() | 返回迭代中的下一个元素 |
| boolean hasNext() | 如果迭代具有更多元素,则返回true |
| E previous() | 返回列表中的上一个元素 |
| boolean hasPrevious() | 如果此列表迭代器在相反方向遍历列表时具有更多的元素,则返回true |
| void add(E e) | 将指定的元素插入列表 |
package com.study_04;import java.util.ArrayList;import java.util.List;import java.util.ListIterator;public class ListIteratorDemo {public static void main(String[] args) {// 创建一个集合对象List<String> list = new ArrayList<>();// 添加元素:boolean add(E e)list.add("hello");list.add("world");list.add("java");// 正向迭代// ListIterator<String> lit = list.listIterator();// while (lit.hasNext()){// String s = lit.next();// System.out.println(s);// }// System.out.println("--------------");// 反向迭代 此时lit指向尾部// while (lit.hasPrevious()){// String s = lit.previous();// System.out.println(s);// }// 获取列表迭代器ListIterator<String> lit = list.listIterator();while (lit.hasNext()){String s = lit.next();// 在迭代期间修改列表,并获取列表中迭代器的当前位置if (s.equals("world")) {lit.add("javase");}}System.out.println(list);}}
LinkedLsit集合特有功能
| 方法名 | 说明 |
|---|---|
| public void addFirst(Ee) | 在该列表开头插入指定的元素 |
| public void addLast(Ee) | 将指定的元素追加到此列表的末尾 |
| public E getFirst() | 返回此列表中的第一个元素 |
| public E getLast() | 返回此列表中的最后一个元素 |
| public E removeFirst() | 从此列表中删除并返回第一个元素 |
| public E removeLast() | 从此列表中删除并返回最后一个元素 |
package com.study_09;import java.util.LinkedList;public class LinkedListDemo {public static void main(String[] args) {// 创建一个集合对象LinkedList<String> linkedList = new LinkedList<>();linkedList.add("hello");linkedList.add("world");linkedList.add("java");// [hello, world, java]// public void addFirst(Ee):在该列表开头插入指定的元素// public void addLast(Ee):将指定的元素追加到此列表的末尾// linkedList.addFirst("javaSe");// linkedList.addLast("javase");// publicE getFirst():返回此列表中的第一个元素// public E getLast():返回此列表中的最后一个元素// System.out.println(linkedList.getFirst());// System.out.println(linkedList.getLast());// public E removeFirst():从此列表中删除并返回第一个元素// public E removeLast():| 从此列表中删除并返回最后一个元素 |System.out.println(linkedList.removeFirst());System.out.println(linkedList.removeLast());System.out.println(linkedList);}}
Set集合
Set集合特点
- 不包含重复元素的集合
- 没有带索引的方法,所以不能使用普通for循环遍历
哈希值
哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类中有一个方法可以获取对象的哈希值
public int hashCode():返回对象的哈希码值
对象的哈希值特点
- 同一个对象多次调用hashCode()方法返回的哈希值是相同的
- 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同
HashSet集合特点
- 底层数据结构是哈希表
- 对集合的迭代顺序不做任何保证,也就是说不保证存储和取出的元素顺序一致
- 没有带索引的方法,所以不能使用普遍for循环
- 由于是Set集合,所以是不包含重复元素的集合
package com.study_03;import java.util.HashSet;public class HashSetDemo {public static void main(String[] args) {// 创建集合对象HashSet<String> hs = new HashSet<>();// 添加元素hs.add("hello");hs.add("world");hs.add("java");hs.add("world");// 遍历for(String s : hs) {System.out.println(s);}}}
package com.study_02;import java.util.Objects;public class Student {private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}public Student() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic int hashCode() {// return super.hashCode();return Objects.hash(name, age); // 重写hashCode方法}}
