美文网首页
java面试集合相关

java面试集合相关

作者: pr0metheus | 来源:发表于2018-03-26 15:21 被阅读0次

准备知识点:

  • java中涉及到集合的接口与实现类都位于java.util包下
  • 集合中接口继承体系如下图所示:


    java集合接口体系.png
  • 集合中各个接口所对应的主要实现类如下图所示:


    集合中接口所对应的主要实现类.png

笔试题目一:

代码如下,问控制台为什么只打印出abc、xyz?

class People {
    String name;
    public People(String name) {
        this.name = name;
    }
    
    public String getName() {
        return this.name;
    }
}
public class HashSetTest {

    public static void main(String[] args) {
        Set<String> set = new HashSet<String>();
        set.add(new String("abc"));
        set.add(new String("xyz"));
        set.add(new String("abc"));
        for (Iterator<String> ite = set.iterator(); ite.hasNext();) {
            String next = ite.next();
            System.out.println(next);
        }
        
    }
}

答案:因为HashSet集合的特性是元素唯一性,而HashSet底层是通过hashcode以及equals方法来判定对象是否唯一的,而String类覆写了equals方法以及hashcode方法这让new String("abc")与new String("abc")的hashcode以及equals方法的比较都为true从而被判定是重复元素无法添加到集合中。

准备知识点:

  • HashSet底层是通过HashMap来实现的
  • HashMap底层是通过Entry数组存储Entry链表来实现的

HashSet增加元素时java底层的操作流程如下:

  • 调用HashMap.put方法来存储key、value
  • 使用hash算法对key.hashCode()计算出一个hash值
  • 让得到的hash值与数组长度 - 1进行&运算得到Entry数组索引位置(该位置用来存储Entry对象,该Entry对象封装了所要添加的key-value对)
  • 得到Entry数组索引后,遍历该索引位置所指向的Entry链表中的Entry元素,如果计算得到的hash值与链表中对象的hash值相等且(key对象是同一个对象或者key对象的内容相等)那么当前所添加的value值覆盖链表中匹配到的元素的value值并返回老的value值,至此HashSet.add方法结束,如果遍历了Entry链表后发现没有一个元素符合条件那么就会将所添加的key对象与value对象封装成一个新的Entry对象并将所计算出来的Entry数组索引指向这个新的Entry对象,而这个新的Entry对象的next属性指向旧的链表,换言之将新生成的Entry对象插入到Entry数组所计算出的索引处所指向的链表头部。

总结:当向集合HashSet中增加对象时,首先集合计算要增加对象的hashCode码,根据该值来得到一个Entry数组索引位置用来存放当前的对象,当在该位置没有一个对象的话,那么HashSet认为该对象在集合中不存在,直接增加进去。如果在该位置有一个Entry对象存在的话,接着将准备增加到集合中的对象与该位置上的Entry链表中的各个Entry对象进行equals方法和hashcode值比较,如果迭代完毕后发现没有一个Entry对象的equals方法以及hashcode值与新增对象相符(注:即比较结果为true),那么集合认为集合中不存在该对象,直接将该对象封装成Entry对象并将其做为数组索引处所指向的Entry链表的头部元素,如果在迭代过程中发现有元素与新增的元素的equals比较以及hashcode值得比较都为true,那么集合认为集合中已经存在该对象了,不会再将该对象增加到集合中去了(注:不过对于HashMap它会将对象的value值替换匹配到的对象的value值并将旧的value值返回)

笔试题目二:

代码如下,控制台会输出什么,并进行相应的解释:

class People {
    String name;
    public People(String name) {
        this.name = name;
    }
    
    public String getName() {
        return this.name;
    }
}
public class HashSetTest {

    public static void main(String[] args) {
        Set<People> set = new HashSet<People>();
        set.add(new People("zhangsan"));
        set.add(new People("lisi"));
        set.add(new People("zhangsan"));
        for (Iterator<People> ite = set.iterator(); ite.hasNext();) {
            People next = ite.next();
            System.out.println(next.getName());
        }
    }
}

答案:控制台会输出zhangsan、lisi、zhangsan。因为People类没有覆写equals以及hashcode方法,从而导致HashSet底层判定它们为不同元素,最终被存储到了集合中。

笔试题目三:

代码如下,控制台会输出什么?为什么?


class People {
    String name;
    public People(String name) {
        this.name = name;
    }
    
    public String getName() {
        return this.name;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (null == obj) return false;
        if (obj instanceof People) {
            People p = (People)obj;
            return p.name.equals(this.name);
        }
        return false;
    }
    
    @Override
    public int hashCode() {
        return this.name.hashCode();
    }
   
}
public class HashSetTest {

    public static void main(String[] args) {
        Set<People> set = new HashSet<People>();
        set.add(new People("zhangsan"));
        set.add(new People("lisi"));
        set.add(new People("zhangsan"));
        for (Iterator<People> ite = set.iterator(); ite.hasNext();) {
            People next = ite.next();
            System.out.println(next.getName());
        }
    }
}

答案:控制台会输出lisi、zhangsan。因为People类重写了equals方法以及hashcode方法,从而在HashSet底层new People("zhangsan")与new People("zhangsan")被判定为重复元素,故无法添加到集合中。

知识点罗列:

  • 当重写equals方法的时候必须重写hashcode方法 (HashMap/HashSet都需要用到这个特性,否则这些对象要存储于HashMap/HashSet集合中的时候会出现重复元素存储的问题,即无法维持元素的唯一性。)
  • 如果一个类的两个对象进行equals方法比较的时候返回true,那么这两个对象必须具有相同的hashcode。(否则存储到HashMap/HashSet里的时候还是无法维持元素的唯一性。注:判定元素重复的条件是:hashcode以及equals方法都返回true)
  • transient修饰的变量无法被序列化到文件中,信息会丢失
  • HashMap对于key为null的存储规则是将它存储在HashMap所维护的Entry数组的第一个元素的链表中(即:key为null的key-value永远存储在数组的第一个元素的链表中)
  • java约定用关键字final修饰的常量名要大写
  • 对于HashSet、HashMap来说,这样做就是为了提高查找效率,使得查找时间不随着set或者map的大小而改变
  • HashMap所维护的Entry数组的默认长度是16
  • HashMap负载因子默认为0.75f(根据经验得到,数组现存储元素个数/数组长度),主要是降低冲突的可能性,当超过该负载因子的时候会扩容数组,不让数组中的Entry链表长度过长而违背HashMap设计的初衷

相关文章

  • Nothing seek,Nothing find

    美图欣赏 Java、Android知识点汇集 Java集合类 ** Java集合相关的博客** java面试相关 ...

  • 【集合框架】

    集合框架(怎么实现、适用场景) hash相关 Java集合框架 Java集合框架综述Java集合框架面试问题集锦 ...

  • java面试集合相关

    准备知识点: java中涉及到集合的接口与实现类都位于java.util包下 集合中接口继承体系如下图所示:jav...

  • Java面试相关---集合

    Collection 集合和数组的区别 A:长度区别 数组的长度固定 集合长度可变 B:内容不同 数组存储的是同一...

  • java面试-集合相关

    最近整天面试厂商的人,我总在问一个很简单的问题,就是集合分为哪几种,都什么区别,怎么用。答的水平参差不齐。所以我想...

  • Java面试相关——集合

    Collection |--List |--ArrayList |--Vector |--LinkedList |...

  • Java面试题收集

    (长期更新)此贴用来收集Java相关的面试题集合 115个Java面试题和答案——终极列表(上) 115个Java...

  • 喜大普奔!70k Star 《Java核心知识面试手册》PDF版

    终于把PDF版本的《Java面试突击手册》搞定!废话不多说,直接上目录: 这份文档是Java 面试相关的文章的集合...

  • Java面试题目录

    垃圾回收 面试题-Java基础-垃圾回收 java垃圾回收 集合 40个Java集合面试问题和答案 Java集合框...

  • Java面试题目录

    垃圾回收 面试题-Java基础-垃圾回收 java垃圾回收 集合 40个Java集合面试问题和答案 Java集合框...

网友评论

      本文标题:java面试集合相关

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