Java容器总结

前言

学习了一些java中的容器,记下总结。

正文

List

ArrayList

ArrayList 底层是由数组实现的,数组的优点是查询效率高,但是插入删除的效率很低,因为每删除一个元素就将该元素后面的所有元素整体往前移动。
ArrayList中声明了Object[] elementData数组,默认大小为10,每当数据插入时首先验证数组是否已经满了,若是数组已满则进行扩容,每次扩容大小为数组当前大小的一半,使用移位运算符>>1。
扩容则是新建一个数组,大小为新长度,然后将原数组数据拷贝到新数组,再指向新数组。类似如下

//在数据满的时候进行扩容
if (i == elementData.length) {
    Object[] newArray = new Object[elementData.length + (elementData.length>>1)];
    System.arraycopy(elementData, 0, newArray, 0, elementData.length);
    elementData = newArray;
}
LinkedList

LinkedList是由双向链表实现的,链表的好处和数组互补,链表插入删除等操作效率很高,因为不需要像类似ArrayList一样将数组整体的移动,同样的查询效率就不高了,需要一个一个遍历。
LinkedList有个Node内部类,包含前一个Node、后一个Node、当前元素。

    private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

其他类似于ArrayList。

Vector

Vector底层是用数组实现的List,相关的方法都加了同步检查,因此线程安全效率低。

List使用

1.需要线程安全时,用Vector。
2.不存在线程安全问题时,查找较多的使用ArrayList。
3.不存在线程安全问题时,增加或删除较多时使用LinkedList.

Map

HashMap

HashMap是键值对来存储的,是综合了数组和链表的存储方式,无序。添加数据时,先对数据key值进行计算得出数组存储的下标,再放入数组相应位置,如果相应位置不空,则链接在单向链表的最后面。
在这里插入图片描述
put方法类似于下面代码:

    public void put(K key, V value) {
        Node<K,V> newNode = new Node();
        newNode.key = key;
        newNode.value = value;
        newNode.next = null;
        boolean keyRepeat = false;//重复标识
        Node lastNode = null;
        //计算hash值来存放数组对应位置
        newNode.hash = myHash(key.hashCode(), table.length);
        Node temp = table[newNode.hash];
        //对应位置为空,则直接放入,否则遍历放到链表最后面
        if (temp == null) {
            table[newNode.hash] = newNode;
            size ++;
        } else {
            //遍历进行操作
            while (temp != null) {
                //重复就覆盖
                if (temp.key.equals(newNode.key)) {
                    temp.value = newNode.value;
                    keyRepeat = true;
                    break;
                } else {
                    lastNode = temp;
                    temp = temp.next;
                }
            }
            //如果不重复则链接到链表最后
            if (!keyRepeat) {
                lastNode.next = newNode;
                size ++;
            }
        }
    }

    //通过hashcode计算返回hash,length必须满足为2^n。
    private int myHash(int hash, int length) {
        System.out.println("my hash is:" + (hash & (length-1)) );
        return (hash & (length - 1));
    }

hash值一开始计算是按除取余来算,但是除法效率不高,
后面采用hashcode &(length-1)提高效率,再后来先无符号右移>>>16再位异或运算^计算下标。
目的是让各元素均匀的分布在HashMap的数组链表里面,提高查询效率。

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

默认当链表长度大于8时单向链表就转换为红黑树(一种平衡二叉树,保证了遍历深度),大大提高了查询效率。

TreeMap

TreeMap的实现是红黑树进行实现的,是有序的map。所以如果key值是自定义的对象,需要类实现Comparable接口,如Entry:

    class Entry implements Comparable<Entry>{
        int total;
        int score;

        @Override
        public String toString() {
            return "total:" + total + "score:" + score;
        }

        public Entry(int total, int score) {
            this.total = total;
            this.score = score;
        }

        @Override
        public int compareTo(Entry o) {
            if (this.score > o.score) {
                return 1;
            } else if (this.score < o.score){
                return -1;
            } else {
                if (this.total > o.total) {
                    return 1;
                } else {
                    return -1;
                }
            }
        }
    }

Set

Set的底层使用的其实就是Map,利用了Map键不能重复的性质。set的每一个元素都是存储在Map的Key值上,最多包含一个空值。

HashSet

底层使用HashMap实现。

TreeSet

底层使用TreeMap实现。

Collections辅助工具类

Collections是辅助工具类,可以对Collection接口下的集合进行排序和查找。
如对ArrayList:

    List<String> list = new ArrayList<>();
    for (int i = 0;i<10;i++) {
        list.add("gao" + i);
    }
    System.out.println(list);
    
    //按key值排序
    Collections.sort(list);
    System.out.println(list);

    //逆序
    Collections.reverse(list);
    System.out.println(list);
    
    //使无序
    Collections.shuffle(list);
    System.out.println(list);

    Collections.sort(list);
    System.out.println(list);
    
    //Collections.binarySearch方法利用二分法查找元素并返回下标,是基于有序列表的查找。
    // 如果使用shuffle方法后将不适用,除非再使用sort方法。
    System.out.println(Collections.binarySearch(list, "gao1"));
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值