A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 厦门校区 黑马粉丝团   /  2018-10-26 18:49  /  1585 人查看  /  13 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

今天我们进一步学习了集合,请根据自己的理解回答下面问题
1.List接口下都有哪些集合,他们各自有什么特点
2.Set接口下的集合是如何保证无序不可重复的
3.我们为什么要重写HashCode( )和equals()方法?
4.数据在存入Set集合的时候,是先判断HashCode()还是先判断equals(),为什么?
5.Comparable和Comparator两个接口的区别,哪种接口使用的多,为什么?

13 个回复

倒序浏览
1.List接口下都有哪些集合,他们各自有什么特点
List接口下有ArrayList、LinkList、Vector。
Vector是单线程(同步)运行。
ArrayList 底层是数组结构 增删慢,查找快
LinkList 底层是链结构,增删快,查找慢
2.Set接口下的集合是如何保证无序不可重复的
先用hash值比较,再用equals方法。
所谓无序并不是随机,是根据自身算法计算出的顺序
3.我们为什么要重写HashCode( )和equals()方法?
如果不重写比较的是地址值,重写后才是比较具体的hash值。
4.数据在存入Set集合的时候,是先判断HashCode()还是先判断equals(),为什么?
先判断HashCode(),hash值具有相对唯一性,equals是用来防止hash对冲的防护措施。
5.Comparable和Comparator两个接口的区别,哪种接口使用的多,为什么
Comparator,因为它是外部比较器,不用实现接口。且规则可以再类中直接重写改变排序规则。

点评

o( ̄▽ ̄)d  发表于 2018-10-29 18:08

评分

参与人数 1技术分 +1 收起 理由
厦门校区 + 1 赞一个!

查看全部评分

回复 使用道具 举报 1 0
1,Vector ArrayList都是类似数组类型存储模式 查找快 增删慢
   LinkedList,是以链表模式存储 查找慢 增删快
2.用hashcode()和equals()保证不重复,存储位置是系统随机指定的,对用户来说是无序的
3.当传入自定义数据类型时 根据用户需求更改相应比较的内容
4.先判断HashSet(),没有相同放在数组的一个位置 ,相同的话发生哈希冲突,在判断equals()是否相同,不同放在数组的同一个位置.
5.前者强制按系统规则进行自然排序,后者可以按照自己的规则进行排序
后者用得多,使用时多是自定义引用数据类型

评分

参与人数 1技术分 +1 收起 理由
厦门校区 + 1 赞一个!

查看全部评分

回复 使用道具 举报
1.List接口下都有哪些集合,他们各自有什么特点?
(1)list接口常见实现类有ArrayList、LinkedList、Vector;
(2)各自的特点
        1)ArrayList:底层采用数组结构,查询快,增删慢
        2)Linked:底层采用链表结构,查询慢,增删快,对内存的空间利用率高
        3)Vector:和Arraylist类似,区别在于它是线程安全型的,所以效率较低,栈内存设计使用到Vector,其它地方
             很少使用
2.Set接口下的集合是如何保证无序不可重复的
(1)以TreeSet和HashSet为例
        1)TreeSet的元素需要内部实现比较器或则创建TreeSet对象的时候传入比较器,通过比较器来判断两个元素的
             大小,如果要存入的元素和原集合中的某个元素相同就不进行存储,从而保证唯一性
        2)HashSet集合在存储元素时,会先调用元素的hashCode()方法,判断当前要存储的元素hash值是否已经
              在集合中存在,如果已经存在(可能是不同元素但是发生hash冲突),就调用equal方法,如果euqal判断
              也是相等,则不进行存储
3.我们为什么要重写HashCode( )和equals()方法?
(1)要存入HashSet集合的元素,必须重写这两个方法,因为HashSet会根据这两个方法判断要存入元素是否已经
        在集合中存在,从而保证存储的唯一性,如果不重写,默认对地址比较,不对内容比较,这样地址不一样,但内
         容一样的元素也会存储进来
4.数据在存入Set集合的时候,是先判断HashCode()还是先判断equals(),为什么?
(1)先判断HashCode(),因为hashCode通过算法获取和内容相关的hash值,速度较快,equals判断速度较慢
         而且hashCode不同肯定是不同的元素,相同可能是相同的元素,也可能是不同元素但是发生hash冲突,这个
         时候再调用equals判断
5.Comparable和Comparator两个接口的区别,哪种接口使用的多,为什么?
(1)Comparator使用比较多,因为Comparator是外部比较器,在使用比较方法的时候当成参数传进去接口,比较
         灵活,修改也比较方便,Comparable是内部比较器,在被比较的元素类定义时实现该接口,修改不方便。




点评

o( ̄▽ ̄)d  发表于 2018-10-29 18:09

评分

参与人数 1技术分 +1 收起 理由
厦门校区 + 1 赞一个!

查看全部评分

回复 使用道具 举报 2 0

今天我们进一步学习了集合,请根据自己的理解回答下面问题
1.List接口下都有哪些集合,他们各自有什么特点
        1)ArrayList集合:
        多线程,速度快,
        查询快:是一个有序的集合,能根据索引找到对应元素
        增删慢:底层是数组结构
        (数组结构要增删都会自动创建一个对应长度的数组,把源数组的元素交给新数组,然后把新数组的地址值交给原来的数组)
        2)LinkedList
        多线程,速度快,
        查询慢: 链表结构,每次查询都会从第一个开始,知道找到对应元素才停止查询
        增删快: 链表结构,是无序的,增删都可以在链表的每一次进行增删,增删操作对链表结构没有影响
        3)Vecotr
        速度慢,线程安全,意味着速度慢,会自动维护集合大的大小
        实际开发用的少
2.Set接口下的集合是如何保证无序不可重复的
        用hashCode方法跟equals方法去保证元素的唯一性
3.我们为什么要重写HashCode( )和equals()方法?
        set集合保证元素唯一,就必须重写HashCode()和equals();
        要通过hashSet存储自定义类型的元素时,为了保证集合对象的唯一性,就必须重写HashCode()和equals()
4.数据在存入Set集合的时候,是先判断HashCode()还是先判断equals(),为什么?
        HashCode()先比较地址值,地址值碰撞时,就用equals判断元素是否不相同,equals比较也不相同则存入Set集合
5.Comparable和Comparator两个接口的区别,哪种接口使用的多,为什么?
        Comparable内部比较器:必须实现Comparable,重写接口中的方法compareTo定义排序的规则
        Comparator外部比较器:不用实现Comparable接口,推荐使用比较灵活(使用多)
       

评分

参与人数 1技术分 +1 收起 理由
厦门校区 + 1 赞一个!

查看全部评分

回复 使用道具 举报
1.List接口下都有哪些集合,他们各自有什么特点。
答:(1)List接口下主要有ArrayList、Vector、LinkedList集合。
(2)他们各自的特点:
(1)ArrayList:底层结构是数组,查询快,增删慢,线程不安全,效率高。
(2)Vector:底层结构是数组,查询快,增删慢,线程安全,效率低。
(3)LinkedList:底层结构是链表,查询慢,增删快,线程不安全,效率高。
2.Set接口下的集合是如何保证无序不可重复的。
答:Set是一个接口,最常用的实现类就是HashSet,以HashSet为例。HashSet类实现了Set接口, 其底层其实是包装了一个HashMap。HashSet采用HashCode算法来存取集合中的元素。将一个key-value对放入HashMap中时,首先根据key的hashCode()返回值决定该Entry的存储位置,如果两个key的hash值相同,那么它们的存储位置相同。如果这个两个key的equals比较返回true。那么新添加的Entry的value会覆盖原来的Entry的value,key不会覆盖。且HashSet中add()中 map.put(e, PRESENT)==null 为false,HashSet添加元素失败。因此,如果向HashSet中添加一个已经存在的元素,新添加的集合元素不会覆盖原来已有的集合元素。
3.我们为什么要重写HashCode( )和equals()方法?
答:因为默认的equals方法是Object的方法,比较的是内存地址;而默认的hashcode方法返回的是对象的内存地址转换成的一个整数,实际上指的的也是内存,两个方法可以理解为比较的都是内存地址。在实际开发的过程中,如果不重写的hashcode和equals方法的话会导致我们存对象的时候,把对象存进去了,取的时候却取不到想要的对象,这时候就需要重写这两个方法了。
如果你重写了equals()方法,那么一定要重写hashCode()方法。当我们在使用形如HashMap, HashSet这样前面以Hash开头的集合类时,hashCode()就会被隐式调用以来创建哈希映射关系。那么为什么在重写equals方法的时候需要重写hashCode方法呢?我们先来看一下Object.hashCode的通用约定(摘《Effective Java》第45页)
1.         在一个应用程序执行期间,如果一个对象的equals方法做比较所用到的信息没有被修改的话,那么,对该对象调用hashCode方法多次,它必须始终如一地返回 同一个整数。在同一个应用程序的多次执行过程中,这个整数可以不同,即这个应用程序这次执行返回的整数与下一次执行返回的整数可以不一致。
2.          如果两个对象根据equals(Object)方法是相等的,那么调用这两个对象中任一个对象的hashCode方法必须产生同样的整数结果。
3.          如果两个对象根据equals(Object)方法是不相等的,那么调用这两个对象中任一个对象的hashCode方法,不要求必须产生不同的整数结果。然而,程序员应该意识到这样的事实,对于不相等的对象产生截然不同的整数结果,有可能提高散列表(hash table)的性能。
如果只重写了equals方法而没有重写hashCode方法的话,则会违反约定的第二条:相等的对象必须具有相等的散列码(hashCode)。
同时对于HashSet和HashMap这些基于散列值(hash)实现的类。HashMap的底层处理机制是以数组的方法保存放入的数据的(Node<K,V>[] table),其中的关键是数组下标的处理。数组的下标是根据传入的元素hashCode方法的返回值再和特定的值异或决定的。
如果该数组位置上已经有放入的值了,且传入的键值相等则不处理,若不相等则覆盖原来的值,如果数组位置没有条目,则插入,并加入到相应的链表中。检查键是否存在也是根据hashCode值来确定的。所以如果不重写hashCode的话,可能导致HashSet、HashMap不能正常的运作。
Java通过hashCode()方法来确定某个对象应该位于哪个bucket中,然后在相应的链表中进行查找.在理想情况下,如果你的hashCode()方法写的足够健壮,那么每个bucket将会只有一个结点,这样无论你的对象放在哪片内存中,我都可以通过hashCode()立刻定位到该区域,而不需要从头到尾进行遍历查找。
当我们调用HashSet的put(Object o)方法时,首先会根据o.hashCode()的返回值定位到相应的bucket中,如果该bucket中没有结点,则将 o 放到这里,如果已经有结点了, 则把 o 挂到链表末端.同理,当调用contains(Object o)时,Java会通过hashCode()的返回值定位到相应的bucket中,然后再在对应的链表中的结点依次调用equals()方法来判断结点中的对象是否是你想要的对象。
4.数据在存入Set集合的时候,是先判断HashCode()还是先判断equals(),为什么?
答:先判断HashCode(。)实际的使用中,一个对象一般有key和value,可以根据key来计算它的hashCode。假设现在全部的对象都已经根据自己的hashCode值存储在不同的存储区域中了,那么现在查找某个对象(根据对象的key来查找),不需要遍历整个集合了,现在只需要计算要查找对象的key的hashCode,然后找到该hashCode对应的存储区域,在该存储区域中来查找就可以了,这样效率也就提升了很多。如果我们对equals方法进行了重写,一定要对hashCode方法重写,以保证相同的对象返回相同的hash值,不同的对象返回不同的hash值。
5.Comparable和Comparator两个接口的区别,哪种接口使用的多,为什么?
答:Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次,不能经常修改类的代码实现自己想要的排序。这种方法比较死板,所以用得比较少。
Comparator强行对某个对象进行整体排序。可以将Comparator 传递给sort方法(如Collections.sort或Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。这种方式比较灵活,所以用得比较多。

点评

优秀  发表于 2018-10-29 18:07
o( ̄▽ ̄)d  发表于 2018-10-28 08:00
回复 使用道具 举报 1 0
高质量干货o( ̄▽ ̄)d
回复 使用道具 举报
本帖最后由 陈萱萱 于 2018-10-28 16:24 编辑
zenjack 发表于 2018-10-28 07:48
高质量干货o( ̄▽ ̄)d

互相借鉴!

点评

o( ̄▽ ̄)d  发表于 2018-10-29 18:12
回复 使用道具 举报

1,Vector ArrayList都是类似数组类型存储模式 查找快 增删慢
   LinkedList,是以链表模式存储 查找慢 增删快
2.用hashcode()和equals()保证不重复,存储位置是系统随机指定的,对用户来说是无序的
3.当传入自定义数据类型时 根据用户需求更改相应比较的内容
4.先判断HashSet(),没有相同放在数组的一个位置 ,相同的话发生哈希冲突,在判断equals()是否相同,不同放在数组的同一个位置.
5.前者强制按系统规则进行自然排序,后者可以按照自己的规则进行排序
后者用得多,使用时多是自定义引用数据类型
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马