zoukankan      html  css  js  c++  java
  • 集合源码分析与List操作 与Set集合

    ArrayList, LinkedList,Vector 三者的异同点

    同 : 三个类都实现了List 接口 存储数据的特点相同: 存储有序 可重复
    
    不同 :  ArrayList 作为List的主要实现,线程不安全,效率高, 底层使用Object [] 存储
            LinkedList 对于频繁的使用插入, 删除操作效率比ArrayList效率高 底层使用双向链表存储
    
            Vector 线程安全 效率低 底层使用Object[] elementData存储

    ArrayList源码分析

            ArrayList list = new ArrayList(10);  // 底层创建了长度是10的Object[]数组 elementDate
            list.add(123);  ---> elementData[0] = new Integer(123);
            ...
            list.add();  // 如果此次的添加导致底层的elementData数组容量不够,则扩容,默认情况下扩容为原来的1.5倍
                            同时需要将原有数组中的数据复制到新的数组中
    
            建议开发中使用带参的构造器 :ArrayList list = new ArrayList(int capacity)
    
    
            ArrayList() jdk1.8 源码分析
    
            ArrayList list =  new ArrayList(10)  elementData 初始化为{}并没有创建底层为10 的数组
            list.add(123); 第一次调用add添加操作的时候才创建底层为10 的数组并添加数据
    
            扩容的机制和jdk7的相同
    
            小结: jdk7的ArrayList的对象创建相当于单例模式的饿汉式, jdk8的ArrayList的对象创建相当于单例模式的懒汉式

    LinkedList源码分析

        LinkedList 源码分析
            LinkedList list = new LinkedList()内部声明了Node的类型first和last属性,默认值为null
            list.add(123)// 将123 封装到Node中 创建了Node对象  其中Node就是双向链表的体现

    ArrayList基于Collection自行添加的方法

           /*
            ArraylList   方法
    
            增: add(Object obj)
            删: remove(int index) / remove(Object obj)
            改 : set(int index, Object obj)
            查: get(int index)
            插: add(int index, Object obj)
            长度: size()
            遍历: 1: Iterator 迭代器
                  2: for循环
            */
    List除了从Collection集合继承的方法外,List 集合里添加了一些根据索引来 操作集合元素的方法。
    void add(int index, Object ele):在index位置插入ele元素
    boolean addAll(int index, Collection eles):从index位置开始将eles中
    的所有元素添加进来
    Object get(int index):获取指定index位置的元素
    int indexOf(Object obj):返回obj在集合中首次出现的位置
    int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置 
    Object remove(int index):移除指定index位置的元素,并返回此元素
    Object set(int index, Object ele):设置指定index位置的元素为ele
    List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex 位置的子集合

     set(int index,oldValue);修改index下标的内容为oldValue

            System.out.println(list);  // [1, 0, 1, 3, 4, 5, 6, 7, 8]
            list.set(7,"老王");  // 修改下标为7的内容为老王
            System.out.println(list);  // [1, 0, 1, 3, 4, 5, 6, 老王, 8]

    get(int index);根据下标获取内容,获取index下标的内容

            System.out.println(list);  // [1, 0, 1, 3, 4, 5, 6, 7, 8]
            System.out.println(list.get(2)); // 1

    Set

    HashSet 是Set的主要实现类 线程不安全可以存储null值
        |---- LinkedHashSet 作为HashSet的子类遍历其内部数据结构时可以按照添加顺序遍历
    TreeSet 可以按照添加对象的指定属性 进行排序
    
    
    Set接口中没有添加新的方法 都是使用Collection中的方法
    
    1: 无序性: 不等于随机性 存储的数据再底层中并非按照数组索引的顺序添加,而是根据数据的哈希值来的
    2: 不可重复性 :保证添加的元素按照equals()判断时,不能反回true, 即相同的元素只能添加一个
    
    添加元素的过程:
    
    
            我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,此哈希值接着通过某种蒜放计算出
            在HashSet底层数组中存放的位置(即为: 索引位置),判断数组此位置上是否已经有其他元素
                如果位置上没有其他元素,则把元素a添加到此位置,元素a添加成功 ---->情况1
                如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的哈希值
                如果hash值不同元素a添加成功 ---- > 情况2
                如果hash值相同,进而需要田勇元素a所在类的equals()方法:
                equals()返回true,元素a添加失败,
                equals()返回false,元素a添加成功 --- > 情况3
    
    
           对于添加成功的情况2 和3 而言,元素a与已经存在指定索引位置上的数据以链表的形式存储
           jdk7: 元素a放在的数组中,指向原来的元素
           jdk8: 原来的元素在数组中指向元素a

    set 要求:

    1: 向set中添加的数据,其所在的类一定要重写hashCode()和equals()方法
    2: 重写的hashCode()和equals()尽可能保持一致性, 相等的对象必须具有相等的散列码

    LinkedHashSet() 的使用

    LinkedHashSet作为HashSet的子类,在添加数据的同时,每个数据还维护了两个引用,记录此数据前和数据后一个数据
    
    优点: 对于频繁的遍历操作, LinkedHashSet的效率高于HashSet

    TreeSet 中添加的数据, 要求是相同类的对象

    两种排序方式, 自然排序和Comparable接口和Comparator接口

    TreeSet中添加元素必须是同一类型的  否则会报错 

            // TreeSet中添加的元素必须是同一种类型
            TreeSet set = new TreeSet();
            set.add(123);
            set.add(456);
    //        set.add("AA"); // 报错 因为类型不一致
            System.out.println(set.size());
    
    
            Iterator iterator = set.iterator();
            while (iterator.hasNext()){
                System.out.println(iterator.next());
            }P

     Practice

        public static void main(String[] args) {
            List list = new ArrayList();
            list.add(new Integer(1));
            list.add(new Integer(2));
            list.add(new Integer(2));
            list.add(new Integer(4));
            list.add(new Integer(4));
            List listOne = dumpList(list);
            for (Object integer:listOne
                 ) {
                System.out.println(integer);
            }
        }
    
        public static List dumpList(List list){
            HashSet set = new HashSet();
            set.addAll(list);
            return new ArrayList(set);
        }
    在List内去除重复数字值,要求尽量简单

     

    .

  • 相关阅读:
    第一个爬虫和测试
    数学规律
    自定义手绘
    tqqqy的成绩表
    Linux常用命令-netstat
    文档查看命令 cat more less tail head
    Linux三剑客-常用命令
    IO多路复用模型
    redis 的线程模型
    为什么需要缓存?
  • 原文地址:https://www.cnblogs.com/zhaoyunlong/p/12210446.html
Copyright © 2011-2022 走看看