添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

问题:上面的算法根据什么确定容器中对象的“大小”顺序?

所有可以“排序”的类都实现了 java.lang.Comparable 接口, C omparable 接口中只有一个方法

Publicint compareTo(Object obj)

返回 0 :表示 this==obj

返回正数:表示 this>obj

返回负数:表示 this < obj

实现了 C omparable 接口的类通过实现 comparaTo 方法从而确定该对象的排序方式

equals()与 hashCode ():保证不重复

要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。

于是,Java采用了哈希表的原理。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。

这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。

所以,Java对于eqauls方法和hashCode方法是这样规定的:

1. 如果两个对象相同,那么它们的hashCode值一定要相同

2.如果两个对象的hashCode相同,它们并不一定相同(这里说的对象相同指的是用eqauls方法比较)。 如不按要求去做了,会发现相同的对象可以出现在Set集合中,同时,增加新元素的效率会大大下降。

3. equals()相等的两个对象,hashcode()一定相等 equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。

在object类中,hashcode()方法是本地方法,返回的是对象的地址值,而object类中的equals()方法比较的也是两个对象的地址值,如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了;

在String类中,equals()返回的是两个对象内容的比较,当两个对象内容相等时Hashcode()方法根据String类的重写代码的分析,也可知道hashcode()返回结果也会相等。

以此类推,可以知道Integer、Double等封装类中经过重写的equals()和hashcode()方法也同样适合于这个原则。当然没有经过重写的类,在继承了object类的equals()和hashcode()方法后,也会遵守这个原则。

hashCode()方法被用来获取给定对象的唯一整数。这个整数被用来确定对象被存储在HashTable类似的结构中的位置。默认的,Object类的hashCode()方法返回这个对象存储的内存地址的编号。 hashCode()和equals()定义在Object类中,这个类是所有java类的基类,所以所有的java类都继承这两个方法。

如果我们不重写这两个方法,将几乎不遇到任何问题,但是有的时候程序要求我们必须改变一些对象的默认实现。

举例说明:

[java]
view plain print
  1. public class TestString{
  2. public static void main(String[] args){
  3. String s1= "Hello" ;
  4. String s2= "World" ;
  5. String s3= "Hello" ;
  6. System.out.println(s1 == s3);
  7. s1= new String( "hello" );
  8. s2= new String( "hello" );
  9. System.out.println(s1 == s2);
  10. System.out.println(s1.equals(s2));
  11. }
  12. }

以上的正确执行是因为我们已经默认重写了String类的equals()方法和hashCode()方法。但是如果是Object类呢?

  1. import java.util.HashSet;
  2. import java.util.Set;
  3. public class TestEquals1{
  4. public static void main(String[] args){
  5. Cat cl= new Cat( 1 , 2 , 3 );
  6. Cat c2= new Cat( 1 , 2 , 3 );
  7. System.out.println(cl==c2);
  8. System.out.println(cl.equals(c2));
  9. }
  10. }
  11. class Cat{
  12. int color,height,weight;
  13. public Cat( int color, int height, int weight){
  14. this .color=color;
  15. this .height=height;
  16. this .weight=weight;
  17. }
  18. }
  1. public class TestEquals{
  2. public static void main(String[] args){
  3. Cat cl= new Cat( 1 , 2 , 3 );
  4. Cat c2= new Cat( 1 , 2 , 3 );
  5. System.out.println(cl==c2);
  6. System.out.println(cl.equals(c2));
  7. }
  8. }
  9. class Cat{
  10. int color,height,weight;
  11. public Cat( int color, int height, int weight){
  12. this .color=color;
  13. this .height=height;
  14. this .weight=weight;
  15. }
  16. public boolean equals(Object obj){
  17. if (obj== null ) return false ;
  18. else {
  19. if (obj instanceof Cat){
  20. Cat c=(Cat)obj;
  21. if (c.color== this .color && c.height== this .height && c.weight== this .weight){
  22. return true ;
  23. }
  24. }
  25. }
  26. return false ;
  27. }
  28. }

以上这些都是针对容器来说的(如何判断set中不重复,如何判断list中的顺序),当然最主要的是解释为什么重写equals()方法必须要重写hashCode()方法的问题。

根据一个类的equals方法(改写后),两个截然不同的实例有可能在逻辑上是相等的,但是,根据Object.hashCode方法,它们仅仅是两个对象。因此,违反了“相等的对象必须具有相等的散列码”。

所以只要重写了equals(),一定要重写hashCode,否则Hash表都会失效,工作不正常。即便你用equals方法比较得到两个对象是相等的结论那你也得不到相同的哈希码

即如果cat类只重写了equals(),hashcode没有被重写,加入元素时使用的hashcode()是继承于set<-collection<-object的,所以计算的hashcode值不同,存储位置不同,则认为元素不相同,也就能明白为什么上面的判断是否存在(System.out.println(cat.contains(newCat(1,2,3))))时输入的结果为false了。

Java 系列之: 比较 两个list中的内容,返回list1中有但list2中没有的数据,当list1和list2数据相同时返回空的list 方法主要用于返回list1中有但list2中没有的数据 当list1和list2数据相同时返回空的list import java .util.*; public class CompareList { //方法主要用于返回list1中有的数据,而list2没有的 //当list1和list2数据相同时返回空的list public stati 1. 场景描述通过 java 代码从外围接口中获取数据并落地,已经存在的不落地,不存在的落地,因有部分字段变化是正常的,只需比对3个字段相同即为相同。2. 解决方案设置定时任务( 个标签完成springboot定时任务配置),比对接口中获取的数据和本地落地的数据是否相同。2.1 真实代码@Scheduled(cron = "0 10 2 * * ? ")public void execAppUser(... 集合 框架中的PriorityQueue底层使用堆结构,因此其内部的元素必须要能够比大小,PriorityQueue采用了: Comparble和Comparator两种方式。 1. Comparble是默认的内部 比较 方式,如果用户插入自定义类型 对象 时,该类 对象 必须要 实现 Comparble接口,并覆写compareTo方法 2. 用户也可以选择使用 比较 对象 ,如果用户插入自定义类型 对象 时,必须要提供一个 比较 器类,让该类 实现 Comparator接口并覆写compare方法。 Java 集合 框架从整体上可以分为两大家族。 1、 Collection(接口)家族。该接口下的所有子孙均存储的是单一 对象 。 Add(s) 2、 Map(接口)家族。该接口下的所有 Collections和Collection的 区别 : Collections是 java .utils下面的类,含有许多 集合 的相关操作的静态方法 Collections是 java .utils下面的接口,是许多 集合 的上级接口   2.Collections的sort方法 sort方法用于对数据 集合 进行大小排序 * 使用给定的 比较 器对给定的列表 笔者之前做项目的时候,写过一个小算法,用来 实现 两张表的数据同步。因为移动端的数据量一般也就几千条,所以便没有关注性能问题。最近开始面试,由于没做过性能测试,只能根据经验判断,想了想还是靠数据说话 比较 好。 集合 A 是新 集合 集合 B 是老 集合 ,现需要筛选出 集合 A 中的新增元素、已更新元素以及 集合 B ... 实现 了Seriazable,所以可用于json的序列化操作 Iterator:进行轮训的时候尽量使用轮询的方法,,内部优化了非空判断,以及异常处理,for循环遍历有风险,可读,不要用于其他方面 优点:尾插效率高,支持随机访问 在add方法里面了,首先会判断容量大小,如果传入的是个空数组则最小容量取默认容量与minCapacity之间的最大值, ensureExpl... Jaccard coefficient:A,B分别代表符合某种条件的 集合 :两个 集合 交集的大小/两个 集合 并集的大小,交集=并集意味着2个 集合 完全重合。 Ochiai coefficient:A,B分别代表符合某种条件的 集合 :两个 集合 的交集大小/两个 集合 大小的几... 1 List 集合 : 被 比较 对象 要重写equals()方法, 调用List中contains()方法,就是用equals()方法 比较 的.                   List 集合 (允许 重复 元素,允许空值) 2 HashSet 集合 (不允许 重复 元素,允许空值): 被 比较 对象 要重写hashCode()方法和重写equals()方法, 两个都要. 3 TreeSet 集合 .(不允许重... 在项目中,我们常常用到两个 集合 的数据比对,找到其中 不同 的数据,在Android里面基本上数据量也不会太大,往往大家都是直接用for循环嵌套搞定,大家有没有想过 当数据量很大的时候,使用for循环嵌套找出不一样的 对象 ,需要多久。本文将为大家介绍一下如果进行高效的数据比对,以及一些特殊场景的应用,收藏起来,你会用到的。 测试耗时会因为设备性能 不同 不同 ,以下为测试设备的硬件 创建...