O conjunto em Java não está ordenado, mas não pode ser repetido. A
camada inferior do HashSet é uma tabela de hash. A desduplicação é obtida chamando os métodos hashcode e equals.
Quando há strings em nosso HashSet, podemos desduplicar por padrão, porque String Reescreveu os métodos hashcode e euqals
public static void main(String[] args) {
HashSet<String> set = new HashSet();
set.add("java");
set.add("c");
set.add("php");
set.add("bigdata");
set.add("java");
//运行结果,给去重了,而且是无序的
System.out.println(set);//[java, c, bigdata, php]
}
}
Mas quando temos classes, como Person, Cat, Dog, classes que escrevemos nós mesmos, mas queremos reiterá-las de acordo com nossas próprias regras, como o nome de Person e idade, porque a classe Person é construída por nós mesmos, se Não temos que reescrever o método, vamos procurar o método hashcode de Object, para que o hashcode de new Person () seja diferente, de forma que cada um seja um novo e seja gerado, mesmo que a idade e o nome sejam os mesmos
public class Demo1 {
public static void main(String[] args) {
HashSet<Person> set1 = new HashSet<>();
set1.add(new Person("aing",50));
set1.add(new Person("bing",10));
set1.add(new Person("ding",20));
set1.add(new Person("ding",20));
//运行结果是即使名字年龄一样,也会输出两个,我们如果想要按照自己的规则去重,这样我们一定要重写hashcode 和euqals方法
System.out.println(set1);//[Person{name='bing', age=10}, Person{name='ding', age=20}, Person{name='aing', age=50}, Person{name='ding', age=20}]
}
}
class Person{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Reescrevemos o método do hashcode. Quando o hashcode for diferente, ele não irá comparar equals, mas será diferente. Se o hashcode for o mesmo, compare o método equals.
public class Demo1 {
public static void main(String[] args) {
HashSet<Person> set1 = new HashSet<>();
set1.add(new Person("aing",50));
set1.add(new Person("bing",10));
set1.add(new Person("ding",20));
set1.add(new Person("ding",20));
//根据年龄和姓名比较的
System.out.println(set1);//[Person{name='ding', age=20}, Person{name='aing', age=50}, Person{name='bing', age=10}]
}
}
class Person{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
//和属性关联,根据属性的值比较,之所以让age*100;是因为怕有可能出现这个name.hashCode()+age 和 下一个name.hashCode()+age加起来的值恰好相等,所以age*100,可以避免这种情况的发生
@Override
public int hashCode() {
//return Objects.hash(name, age);
return name.hashCode()+age*100;
}
}
A camada inferior do TreeSet é uma árvore binária, e o TreeSet ainda está em ordem. Não apenas o hashcode na String, mas também o método compareTo do elemento é chamado, a classe String implementou a interface Comparable e reescreveu o método compareTo, mas se escrevermos o nosso próprio Por exemplo, se você deseja comparar de acordo com suas próprias regras, você deve reescrever o método hashcode e implementar a interface Comparable
public class Demo2 {
public static void main(String[] args) {
TreeSet<String> set = new TreeSet();
set.add("java");
set.add("c");
set.add("php");
set.add("bigdata");
set.add("java");
System.out.println(set);//[bigdata, c, java, php]
}
}
Mas se sua própria classe
reportar o erro “não pode ser convertido para java.lang.Comparable”, porque Person irá procurar pelo método compareTo, mas a classe Person não o implementa, temos que implementar Comparable
public class Demo2 {
public static void main(String[] args) {
TreeSet<Person1> set1 = new TreeSet<>();
set1.add(new Person1("aing",50));
set1.add(new Person1("bing",10));
set1.add(new Person1("ding",20));
set1.add(new Person1("ding",20));
System.out.println(set1);
}
}
class Person1{
String name;
int age;
public Person1(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person1{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Assim, podemos alcançar a ordem, de acordo com nossos atributos
public class Demo2 {
public static void main(String[] args) {
TreeSet<Person1> set1 = new TreeSet<>();
set1.add(new Person1("aing",50));
set1.add(new Person1("bing",10));
set1.add(new Person1("ding",20));
set1.add(new Person1("ding",20));
System.out.println(set1);
}
}
class Person1 implements Comparable{
String name;
int age;
public Person1(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person1 person1 = (Person1) o;
return age == person1.age &&
Objects.equals(name, person1.name);
}
@Override
public int hashCode() {
return name.hashCode()+age*100;
}
@Override
public String toString() {
return "Person1{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//根据类的属性进行排序
@Override
public int compareTo(Object o) {
Person1 person = (Person1)o;
int num = name.compareTo(person.name);
return num==0?age-person.age:num;
}
}