java集合的数据结构与元素有序性

目录

 

1.引言

2.总结

 3.java集合概述

3.1 ArrayList

3.2 LinkedList

3.3 Vector

3.4 HashMap

3.5 LinkedHashMap

3.6 TreeMap

3.7 Hashtable

3.8 HashSet

3.9 LinkedHashSet

3.10 TreeSet


1.引言

本文是对常见的java(1.8)集合的一些总结,不足之处,欢迎看官们在评论区纠正。

2.总结

^_^,先放大招

 3.java集合概述

java集合框架图,摘自菜鸟教程:https://www.runoob.com/java/java-collections.html

3.1 ArrayList

最常用的集合之一。

底层数据结构为数组,数组的默认初始容量为10,当数据的大小大于10的时候,会进行自动扩容,新的容量为旧的容量的1.5倍。

ArrayList的元素可以存在重复,默认情况下元素的输入顺序与输出顺序一致。

可自定义元素比较器,修改元素输出顺序。

public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(3);
        arrayList.add(4);
        arrayList.add(2);
        arrayList.add(5);
        arrayList.add(1);
        arrayList.add(2);
        System.out.println(arrayList); // [3, 4, 2, 5, 1, 2]
        arrayList.sort((p, n) -> n - p);
        System.out.println(arrayList); // [5, 4, 3, 2, 2, 1]
    }

3.2 LinkedList

LinkedList类是双向链表,链表中的每个节点都包含了对前一个和后一个元素的引用。

与ArrayList类似,元素可以存在重复并且默认输出元素顺序和输入元素顺序一致。可自定义比较器用于实现元素输出顺序

LinkedList与ArrayList因为数据结构不同,所以在读写性能上也不一样,LinkedList适用于更多的写入与删除场景下,ArrayList则适用于读取较多的场景。

public static void main(String[] args) {
        LinkedList<Integer> linkedList = new LinkedList<>();
        linkedList.add(3);
        linkedList.add(4);
        linkedList.add(2);
        linkedList.add(5);
        linkedList.add(1);
        linkedList.add(2);
        System.out.println(linkedList); // [3, 4, 2, 5, 1, 2]
        linkedList.sort((p, n) -> n - p);
        System.out.println(linkedList); // [5, 4, 3, 2, 2, 1]
    }

3.3 Vector

Vector继承AbstractList类,实现了List接口,因为在操作方法上都加上了同步锁,是一个相对线程安全的集合。

虽然Vector可以保证单个方法线程安全,但是对于复合操作的查询却并不能做到线程安全,需要调用方自己以Vector为锁来进行操作。

Vector可以再初始化的时候设置扩容参数capacityIncrement,如果在构造方法中设置了capacityIncrement > 0,那么新数组长度就是原数组长度 + capacityIncrement,否则新数组长度就是原数组长度 * 2。

与ArrayList类似,元素可以存在重复并且默认输出元素顺序和输入元素顺序一致。可自定义比较器用于实现元素输出顺序

public static void main(String[] args) {
    Vector<Integer> vector = new Vector<>();
    vector.add(3);
    vector.add(4);
    vector.add(2);
    vector.add(5);
    vector.add(1);
    vector.add(2);
    System.out.println(vector); // [3, 4, 2, 5, 1, 2]
    vector.sort((p, n) -> n - p);
    System.out.println(vector); // [5, 4, 3, 2, 2, 1]
}

3.4 HashMap

底层由 数组+链表+红黑树 实现,

HashMap的增加操作:根据key的hash值计算出一个值,该值当做数组的下标存入到数据。但是如果发现数组中该下标已经有值的存在(hash碰撞),那么旧值和新值则组合成链表存放于该下标上。链表长度超过8则进行判断,如果数组长度小于64那么进行扩容,否则就同一下标的链表转为红黑树。当HashMap进行resize的时候,发现某个数的元素小于等于6,那么会执行untreeify操作,把树再次转为链表。

HashMap内部由 Node<K,V> 数组保存数据,数据的下标是由key的hash得到,因此HashMap不支持自定义排序,并且输出顺序由 key 的hash值决定,所以输出元素的顺序和输入元素顺序无关,因此HashMap不是有序的。

public static void main(String[] args) {
    HashMap<String, String> hashMap = new HashMap<>();
    hashMap.put("1", "A");
    hashMap.put("3", "A");
    hashMap.put("2", "A");
    hashMap.put("4", "A");
    hashMap.put("3", "A");
    System.out.println(hashMap); // {1=A, 2=A, 3=A, 4=A}
}

3.5 LinkedHashMap

LinkedHashMap 继承HashMap,是对HashMap的一层封装。LinkedHashMap可以认为是HashMap+LinkedList,即它既使用HashMap操作数据结构,又使用LinkedList维护插入元素的先后顺序

public static void main(String[] args) {
    LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
    linkedHashMap.put("4", "A");
    linkedHashMap.put("1", "A");
    linkedHashMap.put("3", "A");
    linkedHashMap.put("2", "A");
    linkedHashMap.put("3", "A");
    System.out.println(linkedHashMap); // {4=A, 1=A, 3=A, 2=A}
}

3.6 TreeMap

TreeMap的存储结构是红黑树,红黑树的节点之间是具备可比较性的,因此红黑树是有序的,他的元素输出顺序默认为从小到大,也可以自定义排序规则。

public static void main(String[] args) {
    TreeMap<String, String> treeMap = new TreeMap<>(Comparator.reverseOrder());
    treeMap.put("4", "A");
    treeMap.put("1", "A");
    treeMap.put("3", "A");
    treeMap.put("2", "A");
    treeMap.put("3", "A");
    System.out.println(treeMap); // {4=A, 3=A, 2=A, 1=A}
}

3.7 Hashtable

HashTable内部由数组+链表实现。数组的下标同样由key的hash获取,和HashMap类似。

因此Hashtable不支持自定义排序,并且输出顺序由 key 的hash值决定,所以输出元素的顺序和输入元素顺序无关,因此Hashtable不是有序的。

public static void main(String[] args) {
    Hashtable<String, String> hashtable = new Hashtable<>();
    hashtable.put("4", "A");
    hashtable.put("1", "A");
    hashtable.put("3", "A");
    hashtable.put("2", "A");
    hashtable.put("3", "A");
    System.out.println(hashtable); // {4=A, 3=A, 2=A, 1=A}
}

3.8 HashSet

HashSet的底层其实就是HashMap,它在内部维护了一个HashMap,key为HashMap的key,value为一个PERSENT(一个object对象)。

因此HashSet继承了HashMap的特性,值不能重复,不支持自定义排序,元素的输出顺序仅和hash有关,是个无序的集合。

public static void main(String[] args) {
    HashSet<Integer> hashSet = new HashSet<>();
    hashSet.add(5);
    hashSet.add(3);
    hashSet.add(4);
    hashSet.add(2);
    hashSet.add(5);
    System.out.println(hashSet); // [2, 3, 4, 5]
}

3.9 LinkedHashSet

继承HashSet,底层也有HashMap实现,不同于HashSet, LinkedHashSet内部有一个Entry,用于维护元素的输出顺序。LinkedHashSet值不能重复,元素输出顺序和输入顺序一致,不支持自定义的比较器,是个有序的集合。

public static void main(String[] args) {
    LinkedHashSet<Integer> linkedHashSet = new LinkedHashSet<>();
    linkedHashSet.add(5);
    linkedHashSet.add(3);
    linkedHashSet.add(4);
    linkedHashSet.add(2);
    linkedHashSet.add(5);
    System.out.println(linkedHashSet); // [5, 3, 4, 2]
}

3.10 TreeSet

TreeSet内部维护了一个TreeMap,key为TreeMap的key,value是一个PERSENT的object对象,因此TreeSet特性与TreeMap相当,可以自定义比较器,元素输出的顺序默认从小到大输出,是一个有序集合。

public static void main(String[] args) {
    TreeSet<Integer> treeSet = new TreeSet<>((m,n)->n-m);
    treeSet.add(5);
    treeSet.add(3);
    treeSet.add(4);
    treeSet.add(2);
    treeSet.add(5);
    System.out.println(treeSet); // [5, 4, 3, 2]
}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值