Java——容器(校招准备)

依赖关系

在这里插入图片描述

在这里插入图片描述


底层数据结构

  1. 堆:先进后出
  2. 队列:先进先出
  3. 数组:查找快,增删慢(通过下标找)
  4. 链表:查找慢,增删快
    ·想增删元素只要修改下标指向就行
    ·查找元素需要一个一个找往后找

list接口

  • 它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的)。
  • 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
  • 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。
  • List接口的常用子类有:
    • ArrayList集合(底层数组)
    • LinkedList集合(底层链表)

Set接口

Set接口,它里面的集合,所存储的元素就是不重复的。
HashSet集合

  • HashSet集合,采用哈希表结构存储数据,保证元素唯一性的方式依赖于:hashCode()与equals()方法。
    哈希表底层使用的也是数组机制,数组中也存放对象,而这些对象往数组中存放时的位置比较特殊,当需要把这些对象给数组中存放时,那么会根据这些对象的特有数据结合相应的算法,计算出这个对象在数组中的位置,然后把这个对象存放在数组中。而这样的数组就称为哈希数组,即就是哈希表。
  • 当向哈希表中存放元素时,需要根据元素的特有数据结合相应的算法,这个算法其实就是Object类中的hashCode方法。由于任何对象都是Object类的子类,所以任何对象有拥有这个方法。即就是在给哈希表中存放对象时,会调用对象的hashCode方法,算出对象在表中的存放位置,这里需要注意,如果两个对象hashCode方法算出结果一样,这样现象称为哈希冲突,这时会调用对象的equals方法,比较这两个对象是不是同一个对象,如果equals方法返回的是true,那么就不会把第二个对象存放在哈希表中,如果返回的是false,就会把这个值存放在哈希表中。
  • 总结:保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。

集合中线程安全的类

喂!SHE! 喂是指 vector,S是指 stack, H是指 hashtable,E是指:Eenumeration,外加一个currecthashmap。


Collection 和 Collections的区别

  • Collection是集合类的上级接口,继承与他的接口主要有Set 和List.
  • Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。

ArrayList,Vector,LinkedList的存储性能和特性是什么?


HashMap和Hashtable的区别

  • HashMap和Hashtable都实现了Map接口,因此很多特性非常相似。但是,他们有以下不同点:
  • HashMap允许键和值是null,而Hashtable不允许键或者值是null。
  • Hashtable是同步的,而HashMap不是。因此,HashMap更适合于单线程环境,而Hashtable适合于多线程环境。
  • HashMap提供了可供应用迭代的键的集合,因此,HashMap是快速失败的。另一方面,Hashtable提供了对键的列举(Enumeration)。
  • 一般认为Hashtable是一个遗留的类。

什么是迭代器

terator提供了统一遍历操作集合元素的统一接口, Collection接口实现Iterable接口, 每个集合都通过实现Iterable接口中iterator()方法返回Iterator接口的实例, 然后对集合的元素进行迭代操作.
有一点需要注意的是:在迭代元素的时候不能通过集合的方法删除元素, 否则会抛出ConcurrentModificationException 异常. 但是可以通过Iterator接口中的remove()方法进行删除.


Iterator和ListIterator的区别?

  • Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
  • Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
  • ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。

如果hashMap的key是一个自定义的类,怎么办

使用HashMap,如果key是自定义的类,就必须重写hashcode()和equals()。


Java集合类框架的基本接口有哪些

集合类接口指定了一组叫做元素的对象。集合类接口的每一种具体的实现类都可以选择以它自己的方式对元素进行保存和排序。有的集合类允许重复的键,有些不允许。
Java集合类提供了一套设计良好的支持对一组对象进行操作的接口和类。Java集合类里面最基本的接口有:

  • Collection:代表一组对象,每一个对象都是它的子元素。
  • Set:不包含重复元素的Collection。
  • List:有顺序的collection,并且可以包含重复元素。
  • Map:可以把键(key)映射到值(value)的对象,键不能重复。

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

  • 区别:

    • Array 可以容纳基本类型和对象,而 ArrayList 只能容纳对象。
    • Array 是指定大小的,而 ArrayList 大小是固定的,可自动扩容。
    • Array 没有提供 ArrayList 那么多功能,比如 addAll、removeAll 和 iterator 等。
  • 尽管 ArrayList 明显是更好的选择,但也有些时候 Array 比较好用,比如下面的三种情况:

    • 如果列表的大小已经指定,大部分情况下是存储和遍历它们
    • 对于遍历基本数据类型,尽管 Collections 使用自动装箱来减轻编码任务,- 在指定大小的基本类型的列表上工作也会变得很慢。
    • 如果你要使用多维数组,使用 [][] 比 List 会方便。

HashSet 如何检查重复

  • 如果没有相符的 hashcode ,HashSet会假设对象没有重复出现。
  • 但是如果发现有相同 hashcode 值的对象,这时会调用 equals 方法来检查 hashcode 相等的对象是否真的相同。
    • 如果两者相同,HashSet 就不会让加入操作成功。
    • 如果两者不同,HashSet 就会让加入操作成功。

HashMap工作原理

  • HashMap作为优秀的Java集合框架中的一个重要的成员,在很多编程场景下为我们所用。

  • HashMap内部实现是一个桶数组,每个桶中存放着一个单链表的头结点。其中每个结点存储的是一个键值对整体(Entry),HashMap采用拉链法解决哈希冲突(关于哈希冲突后面会介绍)。
    数组桶:Node<K,V>[]

链边:Node<K,V>继承Map.Entry
有hash值、key、value、next
提供getValue(),getKey(),toString(),equals()等方法。

红黑树:TreeNode<k,v> extends LinkedHashMap.Entry<k,v>
在这里插入图片描述


HashMap的Put()/Get()方法

当调用put操作

public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
}

实际上调用的是:putVal(hash(key), key, value, false, true),这里计算键值K的哈希值,然后将其对应到HashMap的某一个桶(bucket)上;此时找到以这个桶为头结点的一个单链表,然后顺序遍历该单链表找到某个节点的Entry中的Key是等于给定的参数K;若找到,则将其的old V替换为参数指定的V;否则直接在链表尾部插入一个新的Entry节点。

具体过程:
1.判断当前桶是否为空,空的就需要初始化(resize 中会判断是否进行初始化)。
2.根据当前 key 的 hashcode 定位到具体的桶中并判断是否为空,为空表明没有 Hash 冲突就直接在当前位置创建一个新桶即可。
3.如果当前桶有值( Hash 冲突),那么就要比较当前桶中的 key、key 的 hashcode 与写入的 key 是否相等,相等就赋值给 e,在第 8 步的时候会统一进行赋值及返回。
4.如果当前桶为红黑树,那就要按照红黑树的方式写入数据。
5.如果是个链表,就需要将当前的 key、value 封装成一个新节点写入到当前桶的后面(形成链表)。
6.接着判断当前链表的大小是否大于预设的阈值,大于时就要转换为红黑树。
7.如果在遍历过程中找到 key 相同时直接退出遍历。
8.如果 e != null 就相当于存在相同的 key,那就需要将值覆盖。
9.最后判断是否需要进行扩容。

对于get(K)操作类似于put操作

public V get(Object key) {
        Node<K,V> e;
        return (e = getNode(hash(key), key)) == null ? null : e.value;
    }

实际上getNode就是通过计算键的哈希值,先找到对应的桶,然后遍历桶存放的单链表通过比照Entry的键来找到对应的值。

具体过程:

  1. 首先将 key hash 之后取得所定位的桶。
  2. 如果桶为空则直接返回 null 。 否则判断桶的第一个位置(有可能是链表、红黑树)的 key 是否为查询的 key,是就直接返回 value。
  3. 如果第一个不匹配,则判断它的下一个是红黑树还是链表。
  4. 红黑树就按照树的查找方式返回值。
  5. 不然就按照链表的方式遍历匹配返回值。

为什么修改equal需要同时修改hashcode方法

  • 要保证equal判定相等的对象,hash值也要相等
  • java中的==是比较两个对象在JVM中的地址
  • Object中hashcode默认是与对象的存储地址相关
  • Object equal默认是比较当前对象的引用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值