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

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


Java集合面试(看这一篇就够了)_第1张图片
image

(2)Map


Java集合面试(看这一篇就够了)_第2张图片
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 map = new HashMap();
        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 entry : map.entrySet()) {
            System.out.println(
                    "key:" + entry.getKey() + "value:" + entry.getValue());
        }
        // 第二种遍历方式使用entryset中的Iterator
        Iterator> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Entry 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 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> sets = map.entrySet();
        LinkedList> linkedList = new LinkedList>(
                sets);
        // 2.用Collections的sort方法排序list集合
        Collections.sort(linkedList, new Comparator>() {
            @Override
            public int compare(Entry o1,
                    Entry o2) {
                return o1.getValue().compareTo(o2.getValue());
            }
        });

        // 3.将排序后的list赋值给LinkedHashMap
        Map map1 = new LinkedHashMap();
        for (Entry entry : linkedList) {
            map1.put(entry.getKey(), entry.getValue());
        }
        for (Entry 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 map = new HashMap();
map = (HashMap) 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 set2 = new HashSet(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得到线程安全的类。

你可能感兴趣的:(Java集合面试(看这一篇就够了))