Java基础之集合 List、Map和Set

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平衡排序二叉树(红黑树)结构,按自然排序或比较器存入元素以保证元素顺序。非线程安全。

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容