Java集合面试(看这一篇就够了)

1.集合共分为两大分支:Collection和Map,接下来解释下类图
(1)Collection


image

(2)Map


image

由于HashSet的内部实现原理使用了HashMap,所以先介绍Map集合,然后介绍Collection集合
2.内部实现原理
数组:连续的内存空间,查找快,增删慢

链表:不连续的存储空间,查找慢,增删快
哈希表:由数组和链表组成,HashMap底层实现是基于哈希表。
Hash碰撞:不同的key通过hash算法算出来的值有可能一样,这就是hash碰撞。
3.HashMap和Hashtable的区别( 注意table是小写的t)
(1).HashMap:线程不安全效率高的,键值可以为null。
(2).Hashtable:线程安全效率低的,查看源码发现内部是通过sychronized实现的,而且键值不能为null。
(3).多线程环境下,通常用HashMap和Collections工具类一起使用实现线程安全,下面有介绍。
(4)HashMap的key、value值均可为null
Hahtable的key、value值均不可为null
但两者的的key值均不能重复,若添加相同key的键值对,后面的value会自动覆盖前面的value,但不会报错。
a.HashMap的按值排序
由于map集合是键值对的存储方式,比较特殊,所以采用Collections的sort方法进行排序,排序之前必须要先介绍下HashMap的遍历方式

HashMap<Integer, String> map = new HashMap<Integer, String>();
        map.put(7, "序号:" + 7);
        int i = 0;
        while (i < 5) {
            map.put(i, "序号:" + i);
            i++;
        }
        map.put(9, "序号:" + 9);
        map.put(10, "序号:" + 3);
        // 第一种遍历方式:foreach遍历map中的entryset
        for (Entry<Integer, String> entry : map.entrySet()) {
            System.out.println(
                    "key:" + entry.getKey() + "value:" + entry.getValue());
        }
        // 第二种遍历方式使用entryset中的Iterator
        Iterator<Entry<Integer, String>> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Entry<Integer, String> entry = it.next();
            System.out.println(
                    "key:" + entry.getKey() + "value:" + entry.getValue());
        }
        // 第三种遍历方式foreach直接使用map的keyset
        for (Integer key : map.keySet()) {
            System.out.println("key:" + key + "value:" + map.get(key));
        }
        // 第四种遍历方式使用keyset的Iterator
        Iterator<Integer> iterator = map.keySet().iterator();
        while (iterator.hasNext()) {
            Integer key = iterator.next();
            System.out.println("key:" + key + "value:" + map.get(key));
        }

a.使用keyset的方式会遍历两次,所以没有使用EntrySet效率高。
HashMap输出是无序的,这个无序不是指遍历的结果顺序不一样,而是插入顺序不一样。
b.HashMap的按值排序

        // 1.将map集合转成一个LinkedList集合
        Set<Entry<Integer, String>> sets = map.entrySet();
        LinkedList<Entry<Integer, String>> linkedList = new LinkedList<Entry<Integer, String>>(
                sets);
        // 2.用Collections的sort方法排序list集合
        Collections.sort(linkedList, new Comparator<Entry<Integer, String>>() {
            @Override
            public int compare(Entry<Integer, String> o1,
                    Entry<Integer, String> o2) {
                return o1.getValue().compareTo(o2.getValue());
            }
        });

        // 3.将排序后的list赋值给LinkedHashMap
        Map<Integer, String> map1 = new LinkedHashMap();
        for (Entry<Integer, String> entry : linkedList) {
            map1.put(entry.getKey(), entry.getValue());
        }
        for (Entry<Integer, String> entry : map1.entrySet()) {
            System.out.println(
                    "key:" + entry.getKey() + "  value:" + entry.getValue());
        }

c.由于HashMap的key唯一,value是可以重复的,那么怎么让value中重复的去掉呢?
实现方法:将HashMap中的key-value对调,然后赋值给一个新的HashMap集合,此时由于key唯一可以把重复的值去掉,然后再把key-value对调放入另一个新的HashMap集合中。
d.HashMap的线程同步
实现方法:

HashMap<Integer, String> map = new HashMap<Integer, String>();
map = (HashMap<Integer, String>) Collections.synchronizedMap(map);

4.a.ArrayList,LinkedList和Vector的区别
Vector和ArrayList本质都是用数组实现的,而LinkList是用双链表实现的。
Vector是线程安全的,ArrayList是线程不安全的。
扩容:扩容的代价很高,所以能确定容量范围时尽量指定
注意:只有ArrayList和Vector可以指定。

ArrayList arrayList = new ArrayList(100);
arrayList.ensureCapacity(200);
Vector vector = new Vector(100);
vector.ensureCapacity(200);

b.关于list集合的去重

HashSet<Integer> set2 = new HashSet<Integer>(list);
list.clear();
list.addAll(set2);

c.stack的用法
Stack继承于Vector,跟Vector用法差不多。peek()方法pop(),peek是读取栈顶元素,pop是出栈,执行后栈顶元素消失了。
5.HashSet和TreeSet
Set集合的特点是可以去重,他们的内部是基于Map集合的,用的是Map的key,既然要去重,就需要进行比较,比较是基于hashCode和equals方法,必要的时候是需要重写这两个方法的。
6.总结
ArrayList,LinkedList一个无序,一个有序;
HashSet,TreeSet一个无序,一个有序;
HashMap,LinkedHasmMap,一个无序,一个有序;
Vector和HashTable,Stack是线程安全的,但是效率低;
线程不安全的类都可以配合Collections得到线程安全的类。

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

推荐阅读更多精彩内容

  • 、6一、基本知识 1.JDK和JRE的区别 答:JDK是java语言开发工具包,包含JRE和开发工具(javac....
    梦游的沙师弟阅读 1,206评论 0 4
  • Java SE 基础: 封装、继承、多态 封装: 概念:就是把对象的属性和操作(或服务)结合为一个独立的整体,并尽...
    Jayden_Cao阅读 2,106评论 0 8
  • 突然想写写父母的爱情。 父亲比母亲大三岁,父亲巨蟹座,母亲摩羯座。 在父母的那个年代,并不流行什么自由恋爱。他们是...
    米粒儿小姐不忧郁阅读 289评论 0 0
  • 最近刚搬家,没想到日本装个宽带这么难,断网半个多月实在不能忍。好在认识的 dalao 给了一个 boingo 的账...
    Jesse_Zhu阅读 378评论 0 0
  • 今天是来北京的第13天 到现在为止,还对将要学的东西还是蛮期待的,以前上学的时候不喜欢学习,甚至都不知道为什么要学...
    心乐77阅读 156评论 0 0