美文网首页
Java基础之集合 List、Map和Set

Java基础之集合 List、Map和Set

作者: 泡泡之意境 | 来源:发表于2019-08-11 21:28 被阅读0次

    List介绍

    List是Java中比较常用的集合类型之一,它是一个接口,继承于Collection接口,其中实现类中常见的有ArrayList、LinkedList、Vector等子类。
    List中元素可以重复,并且是有序的。(这里的有序指的是按照放入的顺序进行存储。)
    1、ArrayList底层是数组实现的,是一种可以动态增长和缩减的索引序列。数组和数组列表中有一个重大的缺陷:从数组的中间位置删除一个元素要付出很大的代价,因为在数组中处于被删除元素之后的所有元素都要向数组前端移动,在数组中间插入元素也是如此,所以数组在删除和插入的操作上效率低。
    实现:

    public void invoke(){
            //初始化
            List<String> list=new ArrayList<>();
            //赋值
            list.add("one");
            list.add("two");
            list.add("one");
            list.add("one");
            list.add("abc");
            Log.d("TestList","size===="+list.size());
             //遍历集合
            for (int i = 0; i < list.size(); i++) {
                String str=list.get(i);
                Log.d("TestList",str);
            }
    
            Log.d("TestList","------------remove------------");
            //for循环删除元素
            for (int i = 0; i < list.size(); i++) {
                String str=list.get(i);
                if(str.equals("one")){
                    list.remove(i);
                }
                Log.d("TestList",str);
            }
    
        }
    
    TestList: size====5
    TestList: [one, two, one, one, abc]
    TestList: ----for循环remove----
    TestList: [two, one, abc]
    

    通过ArrayList的remove方法进行删除元素打印出的结果中还存在one,出现删除的元素并没有完全被删除的情况。

            Log.d("TestList","----遍历器删除----");
            for (String s : list) {
                if(s.equals("one")){
                    list.remove(s);
                }
            }
            Log.d("TestList",list.toString());
    
       通过遍历器删除,报以下异常
       Caused by: java.util.ConcurrentModificationException
    
            Log.d("TestList","----Iterator----");
            //迭代器删除元素
            Iterator iterator=list.iterator();
            while (iterator.hasNext()) {
                if(iterator.next().equals("one")){
                    iterator.remove();
                }
            }
            Log.d("TestList",list.toString());
    
    TestList: ----Iterator----
    TestList: [two, abc]
    

    通过迭代器判断进行删除元素,打印结果正常。
    综上所述,在对ArrayList进行遍历删除时,建议使用迭代器Iterator进行遍历删除。(面试中被问到的几率还是不小的)
    2、LinkdeList底层是链表实现的。是一种可以在任何位置进行高效的插入和删除的有序序列。链表将每个对象存放在独立的结点中,每个结点还存放着序列中下一个结点的引用。所以在链表中删除一个元素是一个很轻松的操作,只需要对被删除元素附近的结点更新一下即可。在Java程序语言中,所有链表实际上都是双向链接的(doubly linked),每个结点还存放着指向前驱结点的引用。
    实现:

     public void invoke(){
            List<String> list=new LinkedList<>();
            list.add("aaa");
            list.add("abc");
            list.add("aa");
            Log.d("Testlinked",list.toString()+",size===="+list.size());
        }
    
    Testlinked: [aaa, abc, aa],size====5
    
    双向链表
            Log.d("Testlinked","-----Iterator-----");
            Iterator<String> iterator=list.iterator();
            String first=iterator.next();
            String second=iterator.next();
            iterator.remove();
            Log.d("Testlinked",list.toString());
    
    Testlinked: -----Iterator-----
    Testlinked: [aaa, aa]
    
    从链表中删除一个元素

    3、Vector和ArrayList一样底层都是数据实现的,Vector是线程安全的,ArrayList、LinkedList都是线程不安全的,即在多线程下修改数据可能会造成数据错乱,重复增删等问题。Vector中的很多重要方法都是用synchronized实现同步,保证线程安全。在多线程下如果要保证线程安全,那么使用Vector比较好,但是在保证线程安全的同时效率也会下降。如果你的程序不涉及到线程安全问题,那么使用ArrayList是更好的选择(因为Vector使用synchronized,必然会影响效率)。
    Vector和ArrayList二者之间还有一个区别,就是扩容策略不一样。在List被第一次创建的时候,会有一个初始大小,随着不断向List中增加元素,当List认为容量不够的时候就会进行扩容。Vector缺省情况下自动增长原来一倍的数组长度,ArrayList增长原来的50%。

    综上所述,在需要频繁读取集合中的元素时,使用ArrayList效率较高,而在插入和删除操作较多时,使用LinkedList效率较高。使用Vector可以多线程下保证修改数据线程安全(当然,你也可以使用ArrayList并自己实现同步)。

    Set介绍

    Set也是ava中比较常用的集合类型之一,它是一个接口,和List一样继承于Collection接口,其中实现类中常见的有HashSet、TreeSet等子类。Set是没有重复元素的集合,是无序的。
    1、HashSet实现了基于散列表的集。可以用add方法添加元素。可以快速的查看某个元素是否出现在集中,只在某个桶中查找元素,而不必查看集合中的所有元素。HashSet不能存储重复的值,如果key已存在内容会被覆盖。允许null值,非线程安全。
    实现:

    public void invoke(){
            Set<String> set=new HashSet<>();
            set.add("abc");
            set.add("ab");
            set.add("ccc");
            Log.d("TestSet",set.toString());
            //存储null值
            set.add(null);
            Log.d("TestSet",set.toString());
            set.add("oi");
            Log.d("TestSet",set.toString());
            //存储相同的值
            set.add("oi");
            Log.d("TestSet",set.toString());
            //遍历
            Iterator<String> iterator=set.iterator();
            while (iterator.hasNext()) {
            String str=iterator.next();
                Log.d("TestSet",str+"");
            }
        }
    
    TestSet: [abc, ab, ccc]
    TestSet: [null, abc, ab, ccc]
    TestSet: [null, abc, oi, ab, ccc]
    TestSet: [null, abc, oi, ab, ccc]
    

    2、TreeSet类与散列集十分相似,不过,它比散列集有所改进。树集是一个有序的集合。可以以任意顺序将元素插入到集合中。在对集合进行遍历时,每个值会自动的按照排序后的顺序呈现。
    实现:

     public void invoke(){
            Set<Integer> set=new TreeSet<>();
            set.add(777);
            set.add(1);
            set.add(23);
            set.add(98);
            set.add(33);
            set.add(66);
            Log.d("TestTree",set.toString());
        }
    
    TestTree: [1, 23, 33, 66, 98, 777]
    

    Map介绍

    Map是以键值对形式存储数据,不能存储重复的元素。有HashMap、LinkedHashMap、TreeMap等子类。
    1、HashMap是哈希表结构,不保证存取顺序,允许null键或者null值,效率较高。实现了Map接口。

    public void invoke(){
            Map map=new HashMap();
            map.put("aaa","aaa");
            Log.d("TestMap",map.toString());
            map.put(null,null);
            Log.d("TestMap",map.toString());
    
            Log.d("TestMap","aaa==="+map.get("aaa"));
            Log.d("TestMap","null==="+map.get(null));
    }
    
    TestMap: {aaa=aaa}
    TestMap: {null=null, aaa=aaa}
    TestMap: aaa===aaa
    TestMap: null===null
    
    public void invoke(){
            Map map=new HashMap();
            map.put("aaa","aaa");
            map.put("a","aaa");
            map.put("aa","aaa");
            Log.d("TestMap",map.toString());
            //遍历Map
            Iterator iterator = map.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry) iterator.next();
                String key = (String) entry.getKey();
                String value = (String) entry.getValue();
                Log.d("TestMap", "Key = " + key + ", Value = " + value);
            }
    }
    
    TestMap: {aa=aaa, a=aaa, aaa=aaa}
    TestMap: Key = aa, Value = aaa
    TestMap: Key = a, Value = aaa
    TestMap: Key = aaa, Value = aaa
    

    2、LinkedHashMap带双向链表的哈希表结构,保持存取顺序,允许null键和null值,非线程安全,效率较高。

    public void invoke(){
            Map maplink=new LinkedHashMap();
            maplink.put("aaa","123456789");
            maplink.put("aaa","123456789");
            maplink.put("aaa","123456789");
            maplink.put("aaa","123456789");
            Log.d("TestMap",maplink.toString());
    }
    
    TestMap: {aaa=123456789}
    

    3、TreeMap平衡排序二叉树(红黑树)结构,按自然排序或比较器存入元素以保证元素顺序。非线程安全。

    这篇文章主要巩固一下几种集合类相关的基础知识,也加深一下印象,如果文章中有错误有问题,欢迎指出,以后会日益完善。

    相关文章

      网友评论

          本文标题:Java基础之集合 List、Map和Set

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