Java集合相关知识整合

集合是一个存储相同内容的容器。集合类主要由Map和Collection两个根接口派生而成。

在Collection下面有三个子接口来继承它,这三个子接口分别是List接口、Set接口和Queue接口。

List接口:

public interface List<E> extends Collection<E>

Set接口:

public interface Set<E> extends Collection<E>

Queue接口:

public interface Queue<E> extends Collection<E>

Map 接口下面的集合类主要由AbstractMap抽象类和SortedMap接口派生而来。比较常用的集合类有:HashMap,Hashtable,TreeMap,ConcurrentHashMap

AbstractMap抽象类:

public abstract class AbstractMap<K,V> implements Map<K,V>

 SortedMap接口:

public interface SortedMap<K,V> extends Map<K,V> 

常用集合类:

各类集合详解 :

List集合:

1、有序集合(存储和取出元素顺序相同)

2、有索引(可以使用普通for循环遍历)

3、元素可以重复(允许存储重复数据)

List集合下面有ArrayList、LinkedList、vector等子类他们的区别和联系有下表

ArrayListLinkedListVector
底层数据结构动态数组双向循环链表动态数组
特点查询快,增删慢查询慢,增删快查询快,增删慢
线程安全性不安全不安全安全

ArrayList :基于动态数组实现,容量能自动增长的集合。随机访问效率高,随机插入、随机删除效率低。线程不安全 

动态数组:当数组容量不足以存放新的元素时,会创建新的数组,然后把原数组中的内容复制到新数组。

LinkedList:可以在任何位置进行插入移除操作的有序集合,它是基于双向链表实现的,线程不安全。LinkedList 功能比较强大,可以实现队列双向队列。 

Vector 是矢量队列,也是基于动态数组实现,容量可以自动扩容。跟 ArrayList 实现原理一样,但是 Vector 是线程安全,使用 Synchronized 实现线程安全,性能非常差,已被淘汰,使用 CopyOnWriteArrayList 替代 Vector

ArrayList 和 Vector 区别

1、ArrayList 线程不安全,Vector 线程安全;
2、ArrayList 在扩容时默认是扩展为原来的1.5 倍+1,Vector 是默认扩展为原来的2倍;
3、ArrayList 支持序列化,Vector 不支持;
4、Vector 提供 indexOf(obj, start) 接口,ArrayList 没有;
5、Vector 构造函数可以指定扩容增加系数,ArrayList 不可以。

ArrayList 与 LinkedList 的区别 

1、ArrayList 的数据结构是动态数组,LinkedList 的数据结构是链表;
2、ArrayList 不支持高效的插入和删除元素,LinkedList 不支持高效的随机访问元素;
3、ArrayList 的空间浪费在数组末尾预留一定的容量空间,LinkedList 的空间浪费在每一个结点都要消耗空间来存储 prev、next 等信息。

Set集合:

1、无序集合(存储和取出元素顺序不同)

2、无索引(不可以使用普通for循环遍历)

3、元素不可以重复(不允许存储重复数据)

List集合下面有HashSet、LinkedHashList、TreeSet等子类他们的区别和联系有下表

HashSetLinkedHashSetTreeSet
底层数据结构哈希表(数组+链表或红黑树)链表+哈希表红黑树
特点查询快,增删快查询快,增删快查询快,增删快
保证唯一性方式重写hashCode()和equals()重写hashCode()和equals()CompareTo()返回0
线程安全性不安全不安全不安全

HashSet:HashSet 是用来存储没有重复元素的集合类 ,底层是HashMap

LinkedHashSet:使用 HashSet 机制实现,由哈希表保证元素唯一,链表保证先进先出(FIFO)的插入顺序,它是一个可以保证插入顺序或是访问顺序的集合类

TreeSet:TreeSet 实现了 SortedSet 接口,意味着可以排序,它是一个有序的集合类,有两种比排序方式自然排序——继承Comparable接口实现compareTo方法比较器排序——继承Comparator接口实现compare方法

HashSet、LinkedHashSet、TreeSet三者区别:

相同点:1)HashSet、LinkedHashSet、TreeSet都实现了Set接口

2)三者都保证了元素的唯一性,即不允许元素重复

3)三者都不是线程安全的

不同点:

1)排序,HashSet不保证元素的顺序;LinkHashSet保证FIFO即按插入顺序排序;TreeSet保证元素的顺序,支持自定义排序规则

2)null值,HashSet和LinkedHashSet允许添加null值;TreeSet不允许添加null值,添加null时会抛出java.lang.NullPointerException异常。

3)性能,理论情况下,添加相同数量的元素, HashSet最快,其次是LinkedHashSet,TreeSet最慢(因为内部要排序)。

1)HashSet使用 :

HashSet的底层是HashMap,

private transient HashMap<E,Object> map;

HashSet类的代码声明如下:

public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable
{...

可以看出HashSet是继承 AbstractSet抽象类 实现了  Set接口

1.1)添加元素:

public class myCollectionAdd {
    public static void main(String[] args) {
        //使用多态,创建一个HashSet对象
        Collection<String> collection = new HashSet<>();
        //输出该集合的内容为空的(重写toString方法)
        System.out.println("重写了toString方法,但是没有对HashSet集合对象做任何操作,因此返回一个空的数组:"+collection);

        // 往HashSet集合中添加元素使用add,返回值只一个boolean值,一般不用接收这个返回值
        Boolean addReturn = collection.add("abc");

        System.out.println("往集合中添加一个元素后的返回值:" + addReturn);
        System.out.println("使用add方法往集合里面添加了元素后:" + collection);

        //添加不同元素
        System.out.println(collection.add("bcd"));
        //无法添加重复元素
        System.out.println(collection.add("abc"));
    }
}

测试结果 :

重写了toString方法,但是没有对HashSet集合对象做任何操作,因此返回一个空的数组:[]
往集合中添加一个元素后的返回值:true
使用add方法往集合里面添加了元素后:[abc]
true
false

1.2) 获取元素:

HashSet没有获取元素的方法

1.3)获取元素个数

//获取元素个数
        System.out.println("platformSet的元素个数为:" + collection.size());

测试结果 :

platformSet的元素个数为:2

 1.4)删除元素

//删除元素
        // 删除不存在的元素"qqq",返回false
        System.out.println(collection.remove("qqq"));
        // 删除存在的元素 "aaa",返回true
        System.out.println(collection.remove("aaa"));

测试结果 :  

false
true

1.5)判断集合是否为空

//判断集合是否为空
        System.out.println("isEmpty:" + collection.isEmpty());

 测试结果 :  

isEmpty:false

1.6)修改元素

HashSet无法修改元素

1.7)遍历元素:两种方式Iterator迭代器和foreach

//遍历元素
        System.out.println("使用Iterator遍历:");
        Iterator<String> collectionIterator = collection.iterator();
        while (collectionIterator.hasNext()){
            System.out.println(collectionIterator.next());
        }
        System.out.println();

        System.out.println("使用foreach遍历:");
        for (String collectionStr: collection) {
            System.out.println(collectionStr);
        }

测试结果: 

使用Iterator遍历:
bcd
abc

使用foreach遍历:
bcd
abc

 1.8)清空集合

//清空集合
        collection.clear();

2)LinkedHashSet 的使用

LinkedHashSet也是Set接口的实现类,底层数据结构是链表和哈希表,哈希表用来保证元素唯一,链表用来保证元素的插入顺序,即FIFO(First Input First Output 先进先出)。

LinkedHashSet类的代码声明如下所示:

public class LinkedHashSet<E>
    extends HashSet<E>
    implements Set<E>, Cloneable, java.io.Serializable {
{...}

从以上代码也能看出,LinkedHashSet类继承了HashSet类。

LinkedHashSet类的使用方法和HashSet基本一样,只需修改下声明处的代码即可:

Set<String> platformSet = new LinkedHashSet<>();

 3)TreeSet的使用

TreeSet也是Set接口的实现类,底层数据结构是红黑树,TreeSet不仅保证元素的唯一性,也保证元素的顺序。

TreeSet类的代码声明如下所示:

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable
{
}

TreeSet类的使用方法和HashSet基本一样,只需修改下声明处的代码即可:

Set<String> platformSet = new TreeSet<>();

Map集合:

HashMapHashtable

TreeMap

ConCurrentHashMap
底层数据结构数组+链表或红黑树(链表长度>8)数组+链表或红黑树(链表长度>8)红黑树数组+链表或红黑树(链表长度>8)
是否允许null键值
线程安全性不安全安全不安全安全

HashMap :是以key-value 键值对形式存储数据,允许 key 为 null(多个则覆盖),也允许 value 为 null。底层结构是数组 + 链表 + 红黑树。 

Hashtable:Hashtable 也是一个哈希散列表,Hashtable 继承于 Dictionary,使用重入锁 Synchronized 实现线程安全,key 和 value 都不允许为 Null。HashTable 已被高性能的 ConcurrentHashMap 代替。

TreeMap :实现了 SotredMap 接口,意味着可以排序,是一个有序的集合。底层数据结构是红黑树结构,TreeMap 中的每个元素都存放在红黑树的节点上,默认使用自然排序,也可以自定排序,线程不安全。

ConCurrentHashMap:采用CAS + Synchronized 实现锁操作,Node 改名为 HashEntry,引入了红黑树保证查询效率,底层数据结构由数组 + 链表 + 红黑树组成,Node 数组默认为 16。

HashMap 与 Hashtable 的区别 

  1. HashMap 线程不安全,效率高,HashTable 线程安全,效率低;
  2. HashMap 和 Hashtable 二者都实现了 Map 接口,HashMap 是继承于 AbstractMap,HashTable 继承于 Dictionary 类;
  3. HashMap 只允许一个 key 为 Null(多个则覆盖),允许多个 value 为 Null,HashTable 中的 key 和 value 都不允许为 null;
  4. 初始容量不一样,HashMap 默认 16,HashTabel 默认 11。
  5. 判断扩容顺序不一样,HashMap 是 put() 之后扩容,HashTabel 是 put() 之前扩容;
  6. 定位存储位置逻辑不一样,HashMap 是在 key.hashcode() 后使用位运算,HashTable 是在 key.hashcode() 后使用取模;

HashMap 与 TreeMap 的区别 

  1. 数据结构不一样,HashMap 基于“数组 + 单链表”实现(达到一定条件时转为红黑树),TreeMap 基于红黑树实现 ;
  2. HashMap 随机存储,TreeMap 默认按 key 的字典升序排序;
  3. HashMap 只允许一个 key 为 Null(多个则覆盖),允许多个 value 为 Null,TreeMap 的 key 不允许为 Null,但允许多个 value 为 Null;
  4. HashMap 效率高,TreeMap 效率低。

HashMap 和 ConcurrentHashMap 的区别

        1、HashMap和ConcurrentHashMap都是继承abstractMap抽象类,HashMap实现了Map接口,ConcurrentHashMap试下你了ConcurrentMap接口。

        2、HashMap的线程不安全,ConcurrentHashMap的线程是安全的,这是因为ConcurrentHashMap通过CAS+synchronized锁,锁住只有当前操作的bucket,同时不影响其他线程操作其他bucket,效率高。

        3、HashMap 只允许一个 key 为 Null(多个则覆盖),允许多个 value 为 Null,ConcurrentHashMap中的 key 和 value 都不允许为 null;

        4、扩容算法不一样,HashMap是当键值对大于阈值则容量扩大到原来的2倍,ConcurrentHashMap是当键值对数量大于等于sizectl,单线程创建新哈希表,多线程复制bucket到新哈希表,扩容2倍。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值