邯郸招聘信息网:Java中HashSet的重复性与判等运算重载

admin 7个月前 (02-27) 科技 40 0
实现原创指令集【的】虚拟<机>

(目录)

  • 还有一个故事……(〖平行世〗界篇)
    • 还有一个美丽【的】梦幻家(园):jAVa.util
    • 【并且还有一个善战】【的】达〖拉崩巴〗:HashSet
  • (还有另外一)个故事(「不是虚假传说」)
    • 《还》有一对涂满毒药【的】夺命双匕:equals ‘<和>’[hashCode
      • 但是为什[么这次标题【里】没有==【的】故事 了[??
      • 『那』hashCode呢??
      • 『那』把骑士圣剑呢??
    • 然后崩巴也准备开启营救公主【的】冒险

『本文地址』:https://www.cNBlogs.com/oberon-zjt0806/p/12367370.html
本文遵循CC BY-NC-SA 4.0协议,转载请注明出处
{特}别说明

本文【的】基本语境是Java如果需要C#{版本请}看这【里】

还有一个故事……(〖平行世〗界篇)

这是一个关于另外一个平行世界——Java中【的】相似【的】故事……

文艺复兴.jpg……

还有一个美丽【的】梦幻家(园):java.util

《在》Java中,巧 了[,‘也有’ 泛[型【的】数据「容」器。<“《不过》”>,Java{【的】「容」器} ‘<和>’[C#“【的】组织方式有些不”同,C#〖是单独开 了[〗一个System.Collections及子命名空间专门用于给「容」器类使用,『{<而>}』Java则是把「容」器连同其他【的】 工具类一起丢到 了[[java.util《这一个大包中》。
<“《不过》”>,「容」器【的】这部分内容似乎《在》Java【里】叫做JCF(Java Collections Framework)

『{<而>}』且,Java似乎不存《在》非泛型版本{【的】「容」器},尽管据说SE 5之前{【的】「容」器}普遍存《在》类【型安】全性问题((当然已经是过去) 了[……),此外,Java还提供 了[对应于一些容‘器【的】功能接口’(『{<而>}』且是泛型接口),方便自定义「容」器类型,例如,List<E>是列表「容」器【的】接口『{<而>}』不(是泛型「容」器),其对应【的】泛型「容」器是ArrayList<E>

Pigeon p = new Pigeon("咕咕咕"); // class Pigeon extends Bird
Cuckoo c = new Cuckoo("子");   // class Cuckoo extends Bird

List<Bird> birds = new List<Bird>() { { add(p); add(c); } };           // 「错误」,List是「容」器接口,不能直接实例化
ArrayList<Bird> flock = new ArrayList<Bird>() { { add(p); add(c); } }; // 正确,『这是一』个泛型为Bird【的】ArrayList「容」器
List<Bird> avians = new ArrayList<Bird>() { { add(p); add(c); } };      // 正确,ArrayList<E>实现 了[List<E>,“可”视为List<E>【的】多态

<匿名内部类>(AIC)

这个神奇【的】初始化写法《在》Java 术语【里】叫做[<匿名内部类>(AIC,Anonymous Inner Class),《在》Java中AIC是被广泛使用『{<而>}』且屡试不爽【的】,主要是用于简化Java代码。AIC【的】出现使得从一个抽象【的】接口或抽象类(无法实例化,不提供实现)「快速重构」一个简单具体类(可以实例化,具有实现)变得非常容易『{<而>}』无需另〖开文件去写类〗,『{<而>}』不会造成太大【的】性能影响(〖因为〗AIC是“随”用随丢【的】)。
<“《不过》”>AIC《有》个不算副作用【的】副作用,〖因为〗AIC「往往需」要实现(《甚至可能是》大量改写)接口或抽象类【的】方法,因此可能会《在》嵌套层数(特别多【的】上下文中)使得原本就比较混乱【的】局面(更加混乱)(特别是采用 了[不当【的】缩进策略【的】时候,〖因为〗AIC【的】写法本身《在》大多数情形下就包含 了[相当多【的】嵌套),导致代码可读性严重下《降》,〖看起来不是很直观〗,〖有碍观瞻〗。
此外,如果某个AIC频繁地出现,『那』么AIC就不『那』么适用 了[,这种情况下建议把当前【的】AIC改成一个【具名】【的】类。

【并且还有一个善战】【的】达〖拉崩巴〗:HashSet

更加巧合【的】是,《在》java.util【里】‘也有’一个HashSet<E>,功能也是作为一个哈希集使用,也就是说它也满足如下两点:

  1. 【元素是】(唯一)【的】
  2. 【元素是】无序【的】

What a COINCI-DANCE~~

『{<而>}』且,‘也是要分两种’情况,值类型下,只要「两个」值相等,『那』么第二个元素就不会『被添加』:

int i = 5;
int j = 5;

HashSet<int> integers = new HashSet<int>();
integers.add(i); // i『被添加』到integers中
integers.add(j); // 没有变化,integers中已经有5 了[

『{<而>}』对于引用类型来说, ‘<和>’[C#类似,也采用引用一致性判断:

// 为 了[简单这【里】不封装 了[,直接上字段
class Student {
    pUBLic int id; 
    public String name;
    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }
}

public class Program {
    public static void main(String[] args) {
        Student s1 = new Student(1, "Tom");
        Student s2 = new Student(2, "Jerry");        
        Student s3 = s1;
        Student s4 = new Student(1,"Tom");
        HashSet<Student> students = new HashSet<Student>();
        students.add(s1); // s1<被加入>students中
        students.add(s2); // s2<被加入>students中
        students.add(s3); // 没有变化,s1已存《在》
        students.add(s4); // s4<被加入>到students中,尽管s4 ‘<和>’[s1长得一样,但《引用》不一致
    }
}

《我甚至是「差不多」拿》上篇文章中【的】代码,几乎没怎么改23333

但是, ‘<和>’[上次一样【的】问题,尽管s4 ‘<和>’[s1《引用》不一致,但实际场合下,我们倾向于把它们当作同一个人,『那』么怎么办呢??

(还有另外一)个故事(「不是虚假传说」)

「不是虚假传说」- 序言[

嗯,这个不是虚假【的】故事,这就是正经【的】解决方案,放心大胆【的】读吧!!

【WPF学习】第四十九章 基本动画

《还》有一对涂满毒药【的】夺命双匕:equals ‘<和>’[hashCode

当然,Java【里】所有对象都继承自java.lang.ObjectObject,『{<而>}』Java对象‘也有’两种相等判别方式:== ‘<和>’[Object.equals

『{<而>}』且, 这俩判别方式一模一[样,“值类型下只要值”相等就可以,『{<而>}』对于引用类型,==判别【的】是引用一致性

但是为什[么这次标题【里】没有==【的】故事 了[??

一直就没有,『那』是你【的】错觉,上一篇【的】==还是虚假【的】故事呢,『{<而>}』且原因也很简单:

Java【里】运算符不允许重载

『{<而>}』且Object【里】没有之前【的】ReferenceEquals,所以==就是引用一致性【的】兜底判别,没法重载【的】话『那』就免谈 了[,<“《不过》”>equals(是父类方)法,当然是可以重载【的】。

『那』hashCode呢??

‘<和>’[隔壁【的】System.Object.GetHashCode()类似地,这边‘也有’一个java.lang.Object.hashCode(),作用也是类似【的】,返回一个用作哈希值【的】数。

『{<而>}』且更加巧合【的】是,这【里】【的】Object.equals() ‘<和>’[hashCode()也没什么关系,{单独改写其中一个函}数【对另外一个函数也都】没什么影响。

最最巧合【的】是, ‘<和>’[隔壁一样,Java也建议equals ‘<和>’[hashCode要改都改
<“《不过》”>之前是〖因为〗非泛型「容」器(比如Hashtable),『{<而>}』这次是真真正正【的】为 了[泛型「容」器。

『{<而>}』HashSet<E>正是使用equals ‘<和>’[hashCode作为双重判据,HashSet<E>『认』为equals返回true,且两者hashCode相等【的】时候,就『认』为是相同【的】元素『{<而>}』不被

『那』把骑士圣剑呢??

非常遗憾,这【里】没有『那』种东西java.util并没有提供类似于IEqualityComparer<T>【的】东西,『{<而>}』HashSet<E>也不〗提供getComparator()这种方法……

java.util只提供这个东西——interface Comparator<T>,其作用 ‘<和>’[C#中【的】IComparer<T>「差不多」,〖因为〗Java不让重载运算符,因此Comparator<T>提供 了[compare方法进行【的】大小比较,『{<而>}』且只是用于比较排序『{<而>}』已。

然后崩巴也准备开启营救公主【的】冒险

{最后把程}序改写成这个「样子」:

import java.util.HashSet;

class Student {
    public int id;
    public String name;
    public Student(int id,String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stub
        return id == ((Student)obj).id && name.equals(((Student)obj).name);
    }
    
    @Override
    public int hashCode() {
        return id;
    }
}

public class HSetTest {
    public static void main(String[] args) {
        Student s1 = new Student(1,"Tom");
        Student s2 = s1;
        Student s3 = new Student(1,"Tom");
        @SuppressWarnings("serial")
        HashSet<Student> students = new HashSet<Student>() {
            {
                add(s1); // s1『被添加』到students中
                add(s2); // 没有变化,s1已存《在》
                add(s3); // 没有变化,s3被『认』为 ‘<和>’[s1逻辑上相等
            }
        };
        
        for(Student s : students) {
            System.out.println(String.format("%d.%s",s.id,s.name));
        }
    }
}

(输)出结果:

1.Tom
,

sunbet

Sunbet www.0-577.com欢迎您【的】加入。

Sunbet声明:该文看法仅代表作者自己,与本平台无关。转载请注明:邯郸招聘信息网:Java中HashSet的重复性与判等运算重载

网友评论

  • (*)

最新评论

标签列表

    文章归档

      站点信息

      • 文章总数:641
      • 页面总数:0
      • 分类总数:8
      • 标签总数:1024
      • 评论总数:256
      • 浏览总数:8003