Java容器总结

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

Java容器总结 - 图1

概述

  • List、Set、Map都是接口,前两个继承至Collection接口,Map为独立接口
  • Set下有HashSetLinkedHashSetTreeSet
  • List下有ArrayListVectorLinkedList
  • Map下有HashTableLinkedHashMapHashMapTreeMap
  • Collection接口下还有个Queue接口,有PriorityQueue类

Collection接口下面有三个接口ListSetQueue

  • LinkedList既可以实现Queue接口,也可以实现List接口,但是当LinkedList实现Queue接口Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时,就完全只能访问Queue接口所定义的方法了,而不是能直接访问LinkedList的非Queue的方法),以使得只有恰当的方法才可以使用
  • SortedSet是个接口,它里面的(只有TreeSet这一个实现可用)中的元素一定是有序的

📚Collection

📒List

有序,可重复

📃ArrayList

优点:底层数据结构是数组,查询快,增删慢

缺点:线程不安全,效率高

📃Vector

优点:底层数据结构是数组,查询快,增删慢

缺点:线程安全,效率低

📃LinkedList

优点:底层数据结构是链表,查询慢,增删快

缺点:线程不安全,效率高

📒Set

无序,唯一

📃HashSet

底层数据结构是哈希表(无序,唯一)

如何保证元素唯一性?

1.依赖两个方法:hashCode()equals()

📃LinkedHashSet

底层数据结构是链表和哈希表(有序,唯一)

  1. 由链表保证元素有序
  2. 由哈希表保证元素唯一

📃TreeSet

底层数据结构是红黑树(有序,唯一)

1.如何保证元素排序的呢?

  1. 自然排序
  2. 比较器排序

2.如何保证元素的唯一性的呢?

根据比较的返回值是否为0来决定

📃总结

  • TreeSet的主要功能用于排序
  • LinkedHashSet的主要功能用于保证FIFO即有序的集合(先进先出)
  • HashSet只是通用的存储数据的集合

📒使用场景

📃唯一:Set

  • 排序:TreeSetLinkedHashSet
  • 不排:HashSet
  • 知道是Set,但是不知道是哪个,就用HashSet

📃不唯一:List

  • 安全:Vector
  • 不安全:ArrayListLinkedList
    • 查询多:ArrayList
    • 增删多:LinkedList
    • 如果知道是List,但是不知道是哪个List,就用ArrayList

📚Map

Map接口有三个比较重要的实现类,分别是HashMapTreeMapHashTable

  • TreeMap是有序的,HashMapHashTable是无序的
  • HashTable的方法是同步的,HashMap的方法不是同步的

这就意味着

  • HashTable是线程安全的,HashMap不是线程安全的
  • HashMap效率高,Has和Table效率较低
    • 如果对同步性或与遗留代码的兼容性没有任何要求,建议使用HashMap。 查看Hashtable的源代码就可以发现,除构造函数外,Hashtable的所有 public 方法声明中都有 synchronized关键字,而HashMap的源码中则没有
  • HashTable不允许null值,HashMap允许null值(key和value都允许)
  • 父类不同:HashTable的父类是DictionaryHashMap的父类是AbstractMap

========================

Collection

Collection集合中通用的功能

Collection集合常用符方法

方法名 说明
boolean add(E e) 添加元素
boolean remove(Object o) 从集合中移除指定的元素
void clear() 清空集合中的元素
boolean contains(Object o) 判断集合中是否存在指定的元素
boolean isEmpty() 判断集合是否为空
int size() 集合的长度
  1. package com.study_01;
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. public class CollectionDemo02 {
  5. public static void main(String[] args) {
  6. // 通过多态的方法创建对象
  7. Collection<String> c = new ArrayList<>();
  8. // add方法永远返回true
  9. // System.out.println(c.add("hello")); // true
  10. c.add("hello");
  11. c.add("java");
  12. c.add("world");
  13. // 删除元素:boolean remove(Object o)
  14. // System.out.println(c.remove("world")); // true
  15. // System.out.println(c.remove("javaee")); // false
  16. // 清除集合中的元素:void clear()
  17. // c.clear();
  18. // 判断集合中是否存在指定的元素:boolean contains(Object o)
  19. // System.out.println(c.contains("world")); // true
  20. // System.out.println(c.contains("javaee")); // false
  21. System.out.println(c.isEmpty()); // 判断集合是否为空
  22. System.out.println(c.size()); // 集合的长度
  23. System.out.println(c);
  24. }
  25. }

Collection集合的遍历

**lterator**:迭代器,集合的专用遍历方式

存在并发修改异常

  • Iterator iterator:返回此集合中元素的迭代器,通过集合的iterator()方法得到
  • 迭代器是通过集合的iterator()方法得到的,所以我们说它是依赖于集合而存在的

**lterator**中的常用方法

  • E next():返回迭代中的下一个元素
  • boolean hasNext():如果迭代具有更多元素,则返回true

增强for循环:简化数组和Collection集合的遍历

  • 实现lterable接口的类允许其对象成为增强型for语句的目标
  • 它是JDK5之后出现的,其内部原理是一个lterator迭代器
  1. for(元素数据类型 变量名:数组或者Collection集合){
  2. //在此处使用变量即可,该变量就是元素
  3. }
  4. int[] arr = {1,2,3,4,5};
  5. // 内部其实是个Iterable迭代器
  6. for (int i :arr) {
  7. System.out.println(i);
  8. }
  1. package com.study_02;
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. import java.util.Iterator;
  5. public class IteratorDemo {
  6. public static void main(String[] args) {
  7. // 创建Collection集合对象 多态
  8. Collection<String> c = new ArrayList<>();
  9. // 添加元素:boolean add(E e)
  10. c.add("hello");
  11. c.add("world");
  12. c.add("java");
  13. // Iterator<E> iterator() 返回此集合中元素的迭代器 通过集合的iterator()方法得到
  14. Iterator<String> it = c.iterator();
  15. /* ----Iterator<E> iterator()-----
  16. public Iterator<E> iterator() {
  17. return new Itr();
  18. }
  19. private class Itr implements Iterator<E> {
  20. ...
  21. }
  22. */
  23. // 用while循环改进判断
  24. // boolean hasNext():如果迭代具有更多元素,则返回true
  25. while (it.hasNext()) {
  26. // E next():返回迭代中的下一个元素
  27. String s = it.next();
  28. System.out.println( s);
  29. }
  30. }
  31. }

List集合特有的功能

List集合特有方法

方法名 说明
void add(String item, int index) 在此集合指定位置插入指定的元素
E remove(int index) 删除指定索引出的元素,返回别删除的元素
E set(int index,E element) 修改指定索引出的元素,返回被修改的元素
E get(int index) 返回指定索引处的元素
  1. package com.study_01;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class ListDemo02 {
  5. public static void main(String[] args) {
  6. List<String> list = new ArrayList<>();
  7. // 添加元素:boolean add(E e)
  8. list.add("hello");
  9. list.add("world");
  10. list.add("java");
  11. // 在此集合指定位置插入指定的元素:void add(String item, int index)
  12. // list.add(1,"javaEE");
  13. // list.add(11,"javaEE"); // IndexOutOfBoundsException 索引越界异常
  14. // 删除指定索引处的元素,返回别删除的元素:E remove(int index)
  15. // System.out.println(list.remove(1)); // world
  16. // System.out.println(list.remove(11)); // IndexOutOfBoundsException 索引越界异常
  17. // 修改指定索引处的元素,返回被修改的元素:Eset(Int index,E element)
  18. // System.out.println(list.set(1,"javaEE")); // world
  19. // System.out.println(list.set(11,"javaEE")); // IndexOutOfBoundsException 索引越界异常
  20. // 返回指定索引处的元素:E get(int index)
  21. // System.out.println(list.get(1)); // world
  22. // System.out.println(list.get(11)); // IndexOutOfBoundsException 索引越界异常
  23. // System.out.println(list);
  24. for (int i = 0; i < list.size(); i++) {
  25. // E next():返回迭代中的下一个元素
  26. String s = list.get(i);
  27. System.out.println(s);
  28. } 34m
  29. }
  30. }

ListIterator列表迭代器

**Iterator**会引发的问题

并发修改异常:ConcurrentModificationException

产生原因:迭代器遍历的过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际修改值不一致‘’

**ListIterator**列表迭代器

  • 通过List集合的listlterator()方法得到,所以说它是List集合特有的迭代器
  • 用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置

**ListIterator**中常用的方法

方法名 说明
E next() 返回迭代中的下一个元素
boolean hasNext() 如果迭代具有更多元素,则返回true
E previous() 返回列表中的上一个元素
boolean hasPrevious() 如果此列表迭代器在相反方向遍历列表时具有更多的元素,则返回true
void add(E e) 将指定的元素插入列表
  1. package com.study_04;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import java.util.ListIterator;
  5. public class ListIteratorDemo {
  6. public static void main(String[] args) {
  7. // 创建一个集合对象
  8. List<String> list = new ArrayList<>();
  9. // 添加元素:boolean add(E e)
  10. list.add("hello");
  11. list.add("world");
  12. list.add("java");
  13. // 正向迭代
  14. // ListIterator<String> lit = list.listIterator();
  15. // while (lit.hasNext()){
  16. // String s = lit.next();
  17. // System.out.println(s);
  18. // }
  19. // System.out.println("--------------");
  20. // 反向迭代 此时lit指向尾部
  21. // while (lit.hasPrevious()){
  22. // String s = lit.previous();
  23. // System.out.println(s);
  24. // }
  25. // 获取列表迭代器
  26. ListIterator<String> lit = list.listIterator();
  27. while (lit.hasNext()){
  28. String s = lit.next();
  29. // 在迭代期间修改列表,并获取列表中迭代器的当前位置
  30. if (s.equals("world")) {
  31. lit.add("javase");
  32. }
  33. }
  34. System.out.println(list);
  35. }
  36. }

LinkedLsit集合特有功能

方法名 说明
public void addFirst(Ee) 在该列表开头插入指定的元素
public void addLast(Ee) 将指定的元素追加到此列表的末尾
public E getFirst() 返回此列表中的第一个元素
public E getLast() 返回此列表中的最后一个元素
public E removeFirst() 从此列表中删除并返回第一个元素
public E removeLast() 从此列表中删除并返回最后一个元素
  1. package com.study_09;
  2. import java.util.LinkedList;
  3. public class LinkedListDemo {
  4. public static void main(String[] args) {
  5. // 创建一个集合对象
  6. LinkedList<String> linkedList = new LinkedList<>();
  7. linkedList.add("hello");
  8. linkedList.add("world");
  9. linkedList.add("java");
  10. // [hello, world, java]
  11. // public void addFirst(Ee):在该列表开头插入指定的元素
  12. // public void addLast(Ee):将指定的元素追加到此列表的末尾
  13. // linkedList.addFirst("javaSe");
  14. // linkedList.addLast("javase");
  15. // publicE getFirst():返回此列表中的第一个元素
  16. // public E getLast():返回此列表中的最后一个元素
  17. // System.out.println(linkedList.getFirst());
  18. // System.out.println(linkedList.getLast());
  19. // public E removeFirst():从此列表中删除并返回第一个元素
  20. // public E removeLast():| 从此列表中删除并返回最后一个元素 |
  21. System.out.println(linkedList.removeFirst());
  22. System.out.println(linkedList.removeLast());
  23. System.out.println(linkedList);
  24. }
  25. }

Set集合

Set集合特点

  • 不包含重复元素的集合
  • 没有带索引的方法,所以不能使用普通for循环遍历

哈希值

哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值

Object类中有一个方法可以获取对象的哈希值

  • public int hashCode():返回对象的哈希码值

对象的哈希值特点

  • 同一个对象多次调用hashCode()方法返回的哈希值是相同的
  • 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同

HashSet集合特点

  • 底层数据结构是哈希表
  • 对集合的迭代顺序不做任何保证,也就是说不保证存储和取出的元素顺序一致
  • 没有带索引的方法,所以不能使用普遍for循环
  • 由于是Set集合,所以是不包含重复元素的集合
  1. package com.study_03;
  2. import java.util.HashSet;
  3. public class HashSetDemo {
  4. public static void main(String[] args) {
  5. // 创建集合对象
  6. HashSet<String> hs = new HashSet<>();
  7. // 添加元素
  8. hs.add("hello");
  9. hs.add("world");
  10. hs.add("java");
  11. hs.add("world");
  12. // 遍历
  13. for(String s : hs) {
  14. System.out.println(s);
  15. }
  16. }
  17. }
  1. package com.study_02;
  2. import java.util.Objects;
  3. public class Student {
  4. private String name;
  5. private int age;
  6. public Student(String name, int age) {
  7. this.name = name;
  8. this.age = age;
  9. }
  10. public Student() {
  11. }
  12. public String getName() {
  13. return name;
  14. }
  15. public void setName(String name) {
  16. this.name = name;
  17. }
  18. public int getAge() {
  19. return age;
  20. }
  21. public void setAge(int age) {
  22. this.age = age;
  23. }
  24. @Override
  25. public int hashCode() {
  26. // return super.hashCode();
  27. return Objects.hash(name, age); // 重写hashCode方法
  28. }
  29. }