小卜java

JAVA面试汇总(三)集合(三)

2022-01-05  本文已影响0人  汤太咸啊

JAVA面试汇总-集合部分,计划四篇,这是第三篇。标题我就按照上一篇的继续,这样每次一部分总结完了,可以直接串起来来个长篇的。

11.集合Set实现Hash怎么防止碰撞

(1)这个实际上问的,HashSet在存入值时候的操作。
(2)HashSet存入的时候,先获取存入值的hashCode,如果HashSet中没有这个hashCode,则认为是新值,直接存入。
(3)如果hashCode相同,这个时候先通过==或者euqals判断,存入的值是否相同,==或者equals有任何一个相同,则认为是相同的值,就返回false。
具体可以看下这一行源码:

if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))

12.数组和链表的区别

(1)数组在内存中连续;链表采用动态内存分配的方式,在内存中不连续,每个节点存储了下个节点的位置
(2)数组长度固定,不支持动态改变数组大小(只能通过复制到新的扩容后的数组中);链表支持动态增加或者删除元素,直接在链上增加或者删除即可
(3)数组在内存中顺序存储,可通过下标访问,访问效率高;链表访问效率低,如果想要访问某个元素,需要从头遍历,查找效率慢
(4)数组可能越界,链表是逐个向后查找,不存在越界
(5)数组适合查找次数多,增加修改次数少的情况;链表适合增加修改次数多,查找次数少的情况。

13.Array和ArrayList有何区别?什么时候更适合用Array

(1)Array是数组;ArrayList是列表
(2)Array声明时候定于长度,且长度不可变;ArrayList不必声明长度,后期达到一定程度,会自动扩容。
(3)Array声明时候定义类型,如下面的String[];ArrayList如果不适用泛型,则可以存入多种类型。

String[] b = new String[10];
b[0] = "0";

(4)知道初始确定的长度且长度不变的时候就可以用Array;不确定长度,而且经常变化可以用ArrayList

14.EnumSet是什么?

(1)EnumSet是一个针对Enum枚举类的集合,抽象类,不能通过new来创建
(2)底层有两个实现,集合中个数超过64个为JumboEnumSet,小于64个为RegularEnumSet
(3)RegularEnumSet通过long作为存储,实际是按照位去存储的,这样非常节省空间,比如我下面那个代码中的实际上就4个内容,存储时候通过二进制的1111(转换为十进制就是15存储到long中),就把全部四个内容存储进入了,如果只有三个内容,TEST_0,TEST_1,TEST_3,那么就存储为1101(转换为十进制就是13存储到long中),即可。
(4)JumboEnumSet超过64位按照long存储费劲了,因此采取了long[]数组来存储,分成64位一组,这样超过64的时候分成多组,比如110个,那就么就是long[0]是满的存储-1,long[1]就是110个Enum-64个Enum=46个Enum,通过位数实际写成46个1,高位补齐0,转换为十进制,就是long[1]=70368744177663。
(5)有一些方法,allOf,noneOf等的操作,具体如下:

import java.util.EnumSet;

public enum TestEnum {
    TEST_0(0),
    TEST_1(1),
    TEST_2(2),
    TEST_3(3);
    private final int value;
    private TestEnum(int value) {
        this.value = value;
    }
    public int getValue() {
        return this.value;
    }
    public static void main(String[] args) {
        System.out.println("EnumSet.allOf");
        EnumSet<TestEnum> set = EnumSet.allOf(TestEnum.class);
        set.forEach(s-> System.out.println(s));
        System.out.println("======");
        System.out.println("EnumSet.noneOf");
        EnumSet<TestEnum> enumSetNone = EnumSet.noneOf(TestEnum.class);
        enumSetNone.forEach(s-> System.out.println(s));
        System.out.println("======");
        System.out.println("EnumSet.add");
        enumSetNone.add(TestEnum.TEST_2);
        enumSetNone.forEach(s-> System.out.println(s));
        System.out.println("======");
        System.out.println("EnumSet.range TEST_0 to TEST_2");
        EnumSet<TestEnum> enumSetRange = EnumSet.range(TestEnum.TEST_0, TestEnum.TEST_2);
        enumSetRange.forEach(s-> System.out.println(s));
        System.out.println("======");
        System.out.println("EnumSet.of");
        EnumSet<TestEnum> enumSOf = EnumSet.of(TestEnum.TEST_0, TestEnum.TEST_2);
        enumSOf.forEach(s-> System.out.println(s));
    }
}
//输出
EnumSet.allOf
TEST_0
TEST_1
TEST_2
TEST_3
======
EnumSet.noneOf
======
EnumSet.add
TEST_2
======
EnumSet.range TEST_0 to TEST_2
TEST_0
TEST_1
TEST_2
======
EnumSet.of
TEST_0
TEST_2

15.Comparable和Comparator接口有何区别?

(1)Comparable接口通过实现类实现compareTo方法来实现实体的比较大小。这样就可以直接使用Collections.sort就可以对实体的List进行排序了,排序的结果是按照compareTo方法比较大小的降序。
(2)Comparator接口是在Collections.sort中直接使用的,可以针对那些没有实现Comparable的实体,或者不按照compareTo去比较排序的情况。

public static void main(String[] args) {
        List<TestComparator> list = new ArrayList<TestComparator>();
        list.add(TestComparator.builder().a("a").b(1).build());
        list.add(TestComparator.builder().a("a1").b(2).build());
        Collections.sort(list,new Comparator<TestComparator>(){
            @Override
            public int compare(TestComparator o1, TestComparator o2) {
                return o2.getB() - o1.getB();
            }
        });
        list.forEach(System.out::println);
    }
    @Data
    @Builder
    static class TestComparator{
        String a;
        int b;
    }
//输出
TestEnum.TestComparator(a=a1, b=2)
TestEnum.TestComparator(a=a, b=1)

感谢各位的阅读,帮忙点赞,感谢各位。

上一篇下一篇

猜你喜欢

热点阅读