1. Descripción general
Set tiene la misma interfaz que Collection, pero el comportamiento es diferente: Set no guarda elementos duplicados y los elementos en la interfaz Set están fuera de servicio.
Lo que necesita saber en esta sección:
¿Qué es una tabla hash?
La parte inferior de la tabla hash también utiliza el mecanismo de matriz. Los objetos se almacenan en la matriz. La ubicación de estos objetos es relativamente especial. Cuando estos objetos se almacenan en la matriz, se calcularán de acuerdo con los datos únicos de estos objetos y el algoritmo correspondiente (código hash) La posición de este objeto en la matriz y luego almacenar este objeto en la matriz. Dicha matriz se denomina matriz hash, es decir, una tabla hash.
Al almacenar elementos en la tabla hash, se llama al método hashCode en la clase Object . Como cualquier objeto es una subclase de la clase Object, cualquier objeto tiene este método. Cabe señalar aquí que si el método hashCode de los dos objetos calcula el mismo resultado, este fenómeno se llama conflicto hash. En este momento, se llamará al método igual del objeto para comparar si los dos objetos son el mismo objeto. Entonces, el segundo objeto no se almacenará en la tabla hash, si el retorno es falso, este valor se almacenará en la tabla hash.
Para garantizar que la unicidad de los elementos Set se determine realmente en función del hashCode del objeto y los métodos iguales. Si almacenamos un objeto personalizado en la colección, para garantizar su unicidad, debemos repetir los métodos hashCode e iguales para establecer un método de comparación que pertenezca al objeto actual.
Ejemplo: comparación de conjunto y lista
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class demo_set无序 {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("aaa");
list.add("ccc");
list.add("aaa");
list.add("bbb");
//不保存重复的元素且无序
Set set=new HashSet();
set.add("ccc");
set.add("aaa");
set.add("bbb");
set.add("aaa");
System.out.println(list);
System.out.println(set);
}
}
Resultado de la operación:
En segundo lugar, HashSet almacena objetos personalizados.
Al usar HashSet para almacenar objetos personalizados, tenemos que anular los métodos hashCode () y equals ()
Porque:
Al llamar al método add () de HashSet, primero determinará si hashCode () es el mismo,
Si es lo mismo, juzgará nuevamente a equals (). Si equals () es igual, entonces no se guardará.
Por ejemplo, dos personas en la clase tienen el mismo nombre y edad, pero deben guardarse.
Ejemplos:
import java.util.HashSet;
public class demo_set添加对象 {
public static void main(String[] args) {
HashSet<Student> hashSet=new HashSet<>();
hashSet.add(new Student("yyy",21));
hashSet.add((new Student("wtc",21)));
//添加重复元素
hashSet.add((new Student("wtc",21)));
System.out.println(hashSet);
}
}
class Student{
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
return super.equals(o);
}
@Override
public int hashCode() {
return this.name.hashCode()+age;
}
@Override
public String toString() {
return "姓名:" + name +
" 年龄:" + age;
}
}
Resultado de la operación:
3. Ejercicios
1. Obtenga 10 números aleatorios no repetidos entre 1-20
import java.util.HashSet;
import java.util.Random;
public class demo_获取10个不重复随机数 {
public static void main(String[] args) {
HashSet hashSet=new HashSet();
Random r=new Random();
while(hashSet.size()<10){
//范围1-20
int i=r.nextInt(20)+1;
hashSet.add(i);
}
System.out.println(hashSet);
}
}
Resultado de la operación:
Cuatro, interfaz TreeSet
Características: 1. Los elementos están ordenados
2. No se pueden almacenar elementos duplicados
Almacenar objetos personalizados: es necesario decirle por qué ordenar
Necesidad de implementar la interfaz: comparable
Método abstracto para implementar la interfaz: compareTo
Escribe las reglas de clasificación en él
Se pueden devolver tres valores en compareTo
* 1. mayor que 0 * 2. menor que 0 * 3. igual a 0 *
Ejemplos:
import java.util.TreeSet;
public class demo_TreeSet {
public static void main(String[] args) {
TreeSet treeSet=new TreeSet();
treeSet.add("aaa");
treeSet.add("ddd");
treeSet.add("bbb");
treeSet.add("ccc");
treeSet.add("aaa");
System.out.println(treeSet);
TreeSet<Students> treeSet1=new TreeSet<>();
treeSet1.add(new Students("yyy",20));
treeSet1.add(new Students("wtc",23));
treeSet1.add(new Students("wt",22));
treeSet1.add(new Students("wtc",20));
System.out.println(treeSet1);
}
}
class Students implements Comparable<Students>{
String name;
int age;
public Students(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Students o) {
//解决年龄相同的问题,按年龄排序
int i=this.age-o.age;
return i==0?this.name.compareTo(o.name):i;
}
@Override
public String toString() {
return "Students{" +
"姓名:" + name +
" 年龄:" + age +
'}';
}
}
Resultado de la operación:
Quinto, el comparador de clasificación se pasa a través del método de construcción.
Resuelva el problema: no puede realizar cambios en la clase de objeto para implementar la interfaz
Ejemplos:
import java.util.Comparator;
import java.util.TreeSet;
public class demo_构造方法传入比较器 {
public static void main(String[] args) {
//第一种写法
Comparator comparator=new Comparator<Person>(){
@Override
public int compare(Person o1, Person o2) {
//实现按年龄排序
int i=o1.age-o2.age;
return i==0?o1.name.compareTo(o2.name):i;
}
};
TreeSet<Person> treeSet=new TreeSet<>(comparator);
/**第二种写法
* TreeSet<Person> treeSet=new TreeSet<>(ew Comparator<Person>(){
* @Override
* public int compare(Person o1, Person o2) {
* //实现按年龄排序
* int i=o1.age-o2.age;
* return i==0?o1.name.compareTo(o2.name):i;
* }
* });
*/
treeSet.add(new Person("YYY",18));
treeSet.add(new Person("wtc",21));
treeSet.add(new Person("wt1",21));
System.out.println(treeSet);
}
}
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 + '\'' +
" 年龄:" + age +
'}';
}
}
Resultado de la operación: