美文网首页java架构经验分享
简单的聊一下JAVA集合(SXL),有什么不对的欢迎指正!

简单的聊一下JAVA集合(SXL),有什么不对的欢迎指正!

作者: 前程有光 | 来源:发表于2021-04-26 21:18 被阅读0次

    一、ArrayList

    数组集合应用

            // ArraysList 增删慢 查询快
            // 根据源码 无参构造方法创建出来的是长度为0的数组{}
            List<Integer> list = new ArrayList<>();
            // 此时add方法进行源码扩容
            list.add(100);
            System.out.println(list.get(0));
    
    

    add()方法扩容源码

        public boolean add(E e) {
            // 不需要关注
            modCount++;
            // e对象 elementData集合数组元素 size当前数组长度
            add(e, elementData, size);
            // 不管成功失败 均返回true
            return true;
        }
        
        private void add(E e, Object[] elementData, int s) {
            // 满足条件 进入扩容算法 不然就进行正常赋值操作
            if (s == elementData.length)
                elementData = grow();
            elementData[s] = e;
            size = s + 1;
        }
        
        private Object[] grow() {
            // 至少需要加一个长度 
            return grow(size + 1);
        }
        
        private Object[] grow(int minCapacity) {
            return elementData = Arrays.copyOf(elementData,
                                               newCapacity(minCapacity));
        }
    
        private int newCapacity(int minCapacity) {
            // overflow-conscious code
            int oldCapacity = elementData.length;
            // 新长度加上旧长度的0.5倍
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            if (newCapacity - minCapacity <= 0) {
                if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
                    // DEFAULT_CAPACITY 默认长度10
                    return Math.max(DEFAULT_CAPACITY, minCapacity);
                // 超出最大二进制,符号会改变,会变为负数
                if (minCapacity < 0) // overflow
                    throw new OutOfMemoryError();
                return minCapacity;
            }
            
            // MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
            return (newCapacity - MAX_ARRAY_SIZE <= 0)
                ? newCapacity
                : hugeCapacity(minCapacity);
        }
    
        private static int hugeCapacity(int minCapacity) {
            if (minCapacity < 0) // overflow
                throw new OutOfMemoryError();
            return (minCapacity > MAX_ARRAY_SIZE)
                ? Integer.MAX_VALUE
                : MAX_ARRAY_SIZE;
        }
    
    

    二、LinkedList

            // LinkedList: 使用双向链表结构,增删快,查找慢
            // (这种结构和ArrayList的数组结构正好是互补状态)
            LinkedList<Integer> ll = new LinkedList<>();
    
            // 模拟栈结构
            // 压栈
            ll.push(100);
            ll.push(200);
            // 弹栈
            Integer i = ll.pop();
            // 200
            System.out.println(i);
            // 1
            System.out.println(ll.size());
    
            // 下面注释参考 不建议使用
            // 添加集合中第一个元素
            // ll.addFirst(100);
            // ll.addFirst(200);
            // 移除集合中第一个元素
            // Integer removeData = ll.removeFirst();
            // 200
            // System.out.println(removeData);
            // 1
            // System.out.println(ll.size());
    
    

    三、Vector

    用法和ArrayList基本一致,是线程安全的。

            // 10 初始化长度 20 扩容增量 此处是相较于ArrayList不同之处
            List<Integer> v = new Vector<>(10, 20);
            v.add(100);
            v.add(200);
    
    

    四、Iterator和ListIterator

            // Iterator 迭代器 作用遍历集合
            // Iterator迭代Collection下List和Set ListIterator迭代List下面的集合
            List<Integer> list = new ArrayList<>();
            list.add(1);
            list.add(2);
            list.add(3);
            list.add(4);
            list.add(5);
    
            Iterator<Integer> iterator = list.iterator();
    
            iterator.next();
            // 必须要有值才能移除即前面调用next()方法,当然没值也会报错
            iterator.remove();;
            // 4
            System.out.println(list.size());
    
            // 判断迭代器下个是否有值
            while(iterator.hasNext()) {
                // 迭代器往下走,并取值
                Integer i = iterator.next();
                // 输出 2 3 4 5
                System.out.println(i);
            }
    
            // 用法和iterator差不多
            ListIterator<Integer> listIterator = list.listIterator();
            // 获取向上走的值
            listIterator.hasPrevious();
            // 添加
            listIterator.add(10);
            // 设置
            listIterator.next();
            listIterator.set(200);
            listIterator.previous();
            // 5
            System.out.println(list.size());
            while(listIterator.hasNext()) {
                // 输出 200 3 4 5
                System.out.println(listIterator.next());
            }
    
    

    五、Set

    Set集合是没有重复的元素,包括null只会存在一个

    5.1 HashSet

            // HashSet是散列存放的数据结构(哈希表)
            // 本质是 map = new HashMap<>()
            // 由于已经存在双值存储的哈希表 所以这边重复利用了形成现在的单值存储的哈希表
            Set<String> set = new HashSet<>();
            // map.put(e, PRESENT)
            set.add("人有悲欢离合");
            set.add("月有阴晴圆缺");
            set.add("但愿人长久");
            set.add("但愿人长久");
            set.add("千里共婵娟");
            set.add("千里共婵娟");
            Iterator<String> iterator = set.iterator();
            while (iterator.hasNext()) {
                System.out.println(iterator.next());
            }
    
    

    5.2 TreeSet

        public static void main(String[] args) {
            // TreeSet 使用二叉树进行存储的 有序(自然顺序)
            Set<Person> set = new TreeSet<>();
            Person p1 = new Person("张三", 13);
            Person p2 = new Person("李四", 14);
            Person p3 = new Person("麻五", 14);
            set.add(p1);
            set.add(p2);
            set.add(p3);
            // 遍历前需制定自己的排序规则, 否则可能报错
            // Person{name='张三', age=13}
            // Person{name='李四', age=14}
            // 比较规则相同的值,不被储存
            for (Person p : set) {
                System.out.println(p);
            }
    
    
            // set.add("C");
            // set.add("B");
            // set.add("A");
            // set.add("D");
            // A B C D
            // Iterator<String> iterator = set.iterator();
            // while(iterator.hasNext()) {
            //    System.out.println(iterator.next());
            // }
        }
    
        static class Person implements Comparable<Person> {
    
            private String name;
    
            private int age;
    
            @Override
            public int compareTo(Person o) {
                // this与0比较
                // 返回this小/0/大
                if (this.age > o.age) {
                    return 1;
                } else if (this.age == o.age) {
                    return 0;
                }
                return -1;
            }
    
            public Person(String name, int age) {
                this.name = name;
                this.age = age;
            }
    
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
            }
    
            public int getAge() {
                return age;
            }
    
            public void setAge(int age) {
                this.age = age;
            }
    
            @Override
            public String toString() {
                return "Person{" +
                        "name='" + name + '\'' +
                        ", age=" + age +
                        '}';
            }
        }
    
    

    六、Map

    Map(Mapping 映射)集合存储的是 键值对 数据,Map的键不可重复。
    影响HashMap的实例化性能的是初始容量和负载因子。
    HashMap/Hashtable/ConcurrentHashMap TreeMap/LinkedHashMap使用方法基本一致。

    HashMap是线程不安全,效率高。HashTable线程安全, 效率低。
    ConcurrentHashMap采用分段锁机制,保证线程安全,效率较高。

    TreeMap是有序的排。
    LinkedHashMap存储有序。

    6.1 HashMap

            Map<String, String> map = new HashMap<>();
            // 存值
            map.put("k1", "v1");
            // 取值 v1
            System.out.println(map.get("k1"));
            map.put("k2", "v2");
    
            // 遍历
            Set<String> set = map.keySet();
            for (String key : set) {
                // k1->v1
                // k2->v2
                System.out.println(key + "->" + map.get(key));
            }
    
            // 转为Collection集合
            Collection<String> c = map.values();
            for (String s : c) {
                System.out.println(s);
            }
    
    

    HashMap源码粗解析

        // 构造方法
        public HashMap() {
            // 默认加载因子0.75f
            this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
        }
    
        public V put(K key, V value) {
            // 先计算键的hash值,然后调用putVal
            return putVal(hash(key), key, value, false, true);
        }
    
        final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                       boolean evict) {
            // n是桶(数组)的长度
            Node<K,V>[] tab; Node<K,V> p; int n, i;
            // table是默认的16个长度的数组赋值给tab
            if ((tab = table) == null || (n = tab.length) == 0)
                // resize扩容算法 n扩容之后的长度
                n = (tab = resize()).length;
            // (n - 1) & hash 是取余后的长度   数组下标没有值直接赋值
            if ((p = tab[i = (n - 1) & hash]) == null)
                tab[i] = newNode(hash, key, value, null);
            else {
                Node<K,V> e; K k;
                // key存在新值覆盖老值
                if (p.hash == hash &&
                    ((k = p.key) == key || (key != null && key.equals(k))))
                    e = p;
                // 判断是树节点 按红黑树套路进行存储 
                else if (p instanceof TreeNode)
                    e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
                // 链表套路进行赋值
                else {
                    for (int binCount = 0; ; ++binCount) {
                        // 非重复值操作
                        if ((e = p.next) == null) {
                            p.next = newNode(hash, key, value, null);
                            // 这边是二叉树操作
                            if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                                treeifyBin(tab, hash);
                            break;
                        }
                        // 重复值操作
                        if (e.hash == hash &&
                            ((k = e.key) == key || (key != null && key.equals(k))))
                            break;
                        p = e;
                    }
                }
                // 前面e被赋值,进入此方法
                if (e != null) { // existing mapping for key
                    V oldValue = e.value;
                    if (!onlyIfAbsent || oldValue == null)
                        e.value = value;
                    afterNodeAccess(e);
                    return oldValue;
                }
            }
            // 增加修改次数
            ++modCount;
            // 判断是否到了临界值
            if (++size > threshold)
                // 扩容
                resize();
            afterNodeInsertion(evict);
            return null;
        }
    
    

    总结

    在文章的最后作者为大家整理了很多资料!包括java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书等等!
    欢迎关注公众号:前程有光,领取!

    相关文章

      网友评论

        本文标题:简单的聊一下JAVA集合(SXL),有什么不对的欢迎指正!

        本文链接:https://www.haomeiwen.com/subject/kolfrltx.html