记录生活中的点点滴滴

0%

Java集合

读《Java核心技术 卷1》集合这一章,书本上基本上看的差不多了,但总觉得不太够,就去网上搜搜一些前人写的Java集合的博客,学习学习,以下大部分内容基本上都是参照 Java集合中List,Set以及Map等集合体系详解(史上最全) 写的。集合盘它!

概述

  • List,Set,Map都是接口,前两个继承Collection接口,Map为独立接口
  • Set下有HashSet,LinkedHashSet,TreeSet
  • List下有ArrayList,Vector,LinkedList
  • Map下有HashMap,LinkedHashMap,TreeMap,Hashtable
  • Collection下还有Queue接口,有PriorityQueue

总结

Collection接口:

List 有序 可重复

  • ArrayList

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

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

  • Vector

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

    缺点:线程安全,效率低

  • LinkedList

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

    缺点:线程安全,效率高

Set 无序 唯一

  • HashSet

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

    如何保证数据唯一性?

    依赖两个方法:hashCode()和equals()

  • LinkedHashSet

    优点:底层数据结构是链表和哈希表。(FIFO插入有序,唯一)

    1、由链表保证元素有序

    2、由哈希表保证元素唯一

  • TreeSet

    优点:底层数据是红黑树。(唯一,有序)

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

    自然排序

    比较器排序

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

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

针对Collection集合我们到底使用谁呢?

唯一吗?

是:Set

排序吗?

是:TreeSet或LinkedHashSet
否:HashSet
如果你知道是Set,但是不知道是哪个Set,就用HashSet。

否:List

要安全吗?

是:Vector
否:ArrayList或者LinkedList

查询多:ArrayList
增删多:LinkedList
如果你知道是List,但是不知道是哪个List,就用ArrayList。

如果你知道是Collection集合,但是不知道使用谁,就用ArrayList。
如果你知道用集合,就用ArrayList。

Map接口:

Map接口有三个比较重要的实现类,分别是HashMap、TreeMap和HashTable

  • TreeMap是有序的,HashMap和HashTable是无序的。
  • HashTable的方法是同步的,HashMap的方法不是同步的。这是二者的主要区别。

这意味着:

  • HashTable是线程安全的,HashMap是线程不安全的。

  • HashMap效率比较高,HashTable效率较低。

    如果对同步性或与遗留代码的兼容性没有任何要求,建议使用HashMap。 查看Hashtable的源代码就可以发现,除构造函数外,Hashtable的所有 public 方法声明中都有 synchronized关键字,而HashMap的源码中则没有。

  • HashTable不允许null值,HashMap允许null值(key和value都允许)。

  • 父类不同:HashMap的父类是AbstractMap,HashTable的父类是Dictionary。

重点问题分析

(一)TreeSet LinkedHashSet HashSet的区别

1、介绍

TreeSet LinkedHashSet HashSet 在Java中都是实现Set的数据结构

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

2、相同点

  • 都实现了Set Interface

  • 三者都是线程不安全的,如果使用线程安全的,可以使用 Collections.synchronizedSet()

3、不同点

  • HashSet插入数据最快,其次是LinkedHashSet,最慢的是TreeSet,因为其内部实现排序

  • HashSet不保证有序,LinkedHashSet保证FIFO即按照插入顺序排序,TreeSet内部实现排序,也可以自定义排序规则

  • HashSet和LinkedHashSet允许存在null数据,但是TreeSet中插入null数据会报空指针异常

4、代码比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void main(String[] args) {
HashSet<String> hashSet = new HashSet<>();
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
TreeSet<String> treeSet = new TreeSet<>();

for (String s : List.of("E", "B", "D", "A", "C")) {
hashSet.add(s);
linkedHashSet.add(s);
treeSet.add(s);
}
//不保证有序
System.out.println("hashSet: "+hashSet);
//按照FIFO
System.out.println("linkedHashSet: "+linkedHashSet);
//内部实现排序
System.out.println("treeSet: "+treeSet);
}

输出结果:

1
2
3
hashSet: [A, B, C, D, E]
linkedHashSet: [E, B, D, A, C]
treeSet: [A, B, C, D, E]

(二)TreeSet的引用类型比较

基本类型会自动排序,引用类型需要我们进行配置。

两种方式:

1、自己写一个比较器,在new TreeSet的时候,传入这个比较器对象即可

1
TreeSet<Person> treeSet = new TreeSet<>(new MyComparator());
1
2
3
public class MyComparator implements Comparator<Person> {
xxx
}

2、引用类实现Comparate接口方法,重写它的CompareTo方法

1
2
3
public class Person implements Comparable<Person> {
xxx
}