public native int hashCode();
演示
package com.westmo1.demo4;
public class MyDemo2 {
public static void main(String[] args) {
MyDemo2 myDemo2 = new MyDemo2();
System.out.println(myDemo2.hashCode());
MyDemo2 myDemo21 = new MyDemo2();
System.out.println(myDemo21.hashCode());
}
}
package com.westmo1.demo4;
public class MyDemo2 {
public static void main(String[] args) {
String abc = new String("abc");
String abc1 = new String("abc");
System.out.println(abc.hashCode());//96354
System.out.println(abc1.hashCode());//96354
System.out.println("重地".hashCode());//1179395
System.out.println("通话".hashCode());//1179395
}
}
(1)底层数据结构是哈希表,元素唯一且无序。
①jdk1.8以前:哈希表=数组+链表
②jdk1.8以后:哈希表=数组+链表+红黑树
(2)数据结构:数组结构:对元素进行了分组(相同哈希值的元素在一组),链表/红黑树结构:将相同哈希值的元素连接到一起
(3) 哈希冲突:两个元素不同,但是哈希值相同,就会发生哈希冲突
package com.westmo1.demo1;
import java.util.HashSet;
public class MyDemo1 {
public static void main(String[] args) {
HashSet strings = new HashSet<>();
strings.add("123");
strings.add("qewq");
for (String string : strings) {
System.out.println(string);
}
}
}
首先add方法会调用hashCode方法来获取字符串"重地"的哈希码值,它的哈希码值是1179395,在集合中找有没有1179395这个哈希码值的元素:
(1)如果有(哈希冲突):"重地"就会调用equals方法和哈希码值相同的元素进行比较:
①返回为true:则两个元素相同,"重地"就不存储到集合中。
②返回为false:则存储到集合中(以链表/红黑数的形式链接到哈希码值相同的元素的后面)。
(2)如果没有:就将"重地"存储到集合中。
所以:HashSet保证元素唯一性是靠重写hashCode()和equals()方法来保证的,如果不重写则无法保证。
package com.westmo1.demo1;
import java.util.HashSet;
public class MyDemo2 {
public static void main(String[] args) {
Student student = new Student("张三", 13);
Student student1 = new Student("张三", 13);
Student student2 = new Student("李四", 15);
Student student3 = new Student("李四", 15);
Student student4 = new Student("王五", 18);
HashSet students = new HashSet<>();
students.add(student);
students.add(student1);
students.add(student2);
students.add(student3);
students.add(student4);
for (Student student5 : students) {
System.out.println(student5);
}
}
}
package com.westmo1.demo1;
import java.util.Objects;
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Student)) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
底层数据结构是由链表和哈希表实现的,链表保证有序,哈希表保证元素唯一。
package com.westmo1.demo1;
import java.util.LinkedHashSet;
public class MyDemo3 {
public static void main(String[] args) {
LinkedHashSet integers = new LinkedHashSet<>();
integers.add(300);
integers.add(100);
integers.add(400);
integers.add(100);
for (Integer integer : integers) {
System.out.println(integer);
}
}
}
TreeSet集合特点:元素唯一,并且可以对元素进行排序,
排序有两种方式:自然排序和使用比较器排序。
package com.westmo1.demo1;
import java.util.TreeSet;
public class MyDemo4 {
public static void main(String[] args) {
TreeSet integers = new TreeSet<>();
/*存储下列元素: 20 , 18 , 23 , 22 , 17 , 24, 19 , 18 , 24*/
integers.add(20);
integers.add(18);
integers.add(23);
integers.add(22);
integers.add(17);
integers.add(24);
integers.add(19);
integers.add(18);
integers.add(24);
for (Integer integer : integers) {
System.out.println(integer);
}
}
}
利用二叉树的数据结构,现存入一个树根,分两个叉,存储元素时,和树根比较,小的放在左边,大的放在右边,如果相等就不存储。
//按照年龄来排序,注意特殊情况
package com.westmo1.demo1;
public class Student1 implements Comparable{
private String name;
private int age;
public Student1(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student1{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student1 o) {
int num=this.age-o.age;
int num1=this.name.compareTo(o.name);
if (num==0) {
num=num1;
}
return num;
}
}
//从例中可以看出,TreeSet集合自然排序需要实现Compraable接口和重写compareTo方法。
package com.westmo1.demo1;
import java.util.TreeSet;
public class MyDemo5 {
public static void main(String[] args) {
Student1 student = new Student1("张三", 13);
Student1 student1 = new Student1("小花", 10);
Student1 student2 = new Student1("李四", 19);
Student1 student3 = new Student1("小明", 17);
Student1 student4 = new Student1("王五", 13);
TreeSet student1s = new TreeSet<>();
student1s.add(student);
student1s.add(student1);
student1s.add(student2);
student1s.add(student3);
student1s.add(student4);
for (Student1 student11 : student1s) {
System.out.println(student11);
}
}
}
//按照姓名的长度排序,注意名字长度相同时,年龄相同时的情况。
package com.westmo1.demo1;
import java.util.TreeSet;
public class MyDemo6 {
public static void main(String[] args) {
Student2 student = new Student2("张三话", 13);
Student2 student1 = new Student2("小花阿叔", 10);
Student2 student2 = new Student2("李四", 19);
Student2 student3 = new Student2("小明的股数打", 17);
Student2 student4 = new Student2("王五", 19);
TreeSet student1s = new TreeSet<>();
student1s.add(student);
student1s.add(student1);
student1s.add(student2);
student1s.add(student3);
student1s.add(student4);
for (Student2 student11 : student1s) {
System.out.println(student11);
}
}
}
package com.westmo1.demo1;
public class Student2 implements Comparable{
private String name;
private int age;
public Student2(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student1{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student2 o) {
int num2=this.name.length()-o.name.length();//先比较名字长度
int num=this.name.compareTo(o.name);//再比较名字的内容
int num1=this.age-o.age;//比较年龄
if (num2==0) {
num2=num;
}
if (num==0) {
num2=num1;
}
return num2;
}
}
自定义的比较器要实现Comparator接口,重写Compare方法。在创建TreeSet对象的时候,就传递一个比较器对象。
package com.westmo1.demo1;
import java.util.Comparator;
import java.util.TreeSet;
public class MyDemo7 {
public static void main(String[] args) {
Student3 student1 = new Student3("小明",15);
Student3 student2 = new Student3("小话",19);
Student3 student3 = new Student3("小明挂个人",10);
Student3 student4 = new Student3("李海华",15);
NameComparable nameComparable = new NameComparable();//姓名比较器
AgeComparable ageComparable = new AgeComparable();//年龄比较器
TreeSet student3s = new TreeSet(nameComparable);//传递姓名比较器对象,也可以用匿名内部类来实现
student3s.add(student1);
student3s.add(student2);
student3s.add(student3);
student3s.add(student4);
for (Student3 student31 : student3s) {
System.out.println(student31);
}
}
static class Student3{
private String name;
private int age;
public Student3(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student3{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
//自定义年龄比较器对象
static class AgeComparable implements Comparator {
@Override
public int compare(Object o1, Object o2) {
Student3 o11 = (Student3) o1;
Student3 o21 = (Student3) o2;
int num=o11.age-o21.age;
int num1=o11.name.compareTo(o21.name);
if (num==0) {
num=num1;
}
return num;
}
}
//自定义姓名比较器对象
static class NameComparable implements Comparator{
@Override
public int compare(Object o1, Object o2) {
Student3 o11 = (Student3) o1;
Student3 o21 = (Student3) o2;
int num=o11.name.length()-o21.name.length();
int num1=o11.name.compareTo(o21.name);
int num2=o11.age-o21.age;
if (num==0) {
num=num1;
}
if (num1==0) {
num=num2;
}
return num;
}
}
}
package com.westmo1.demo1;
import java.util.TreeSet;
public class MyDemo8 {
public static void main(String[] args) {
TreeSet integers = new TreeSet<>();
while(integers.size()<10) {
int random = (int) (Math.random()*20+1);
integers.add(random);
}
for (Integer integer : integers) {
System.out.println(integer);
}
}
}
package com.westmo1.demo1;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
public class MyDemo9 {
public static void main(String[] args) {
//使用匿名内部类来传参,不需要再创建一个类来实现Comparator接口这么麻烦。
TreeSet student4s = new TreeSet(new Comparator() {
@Override
public int compare(Student4 o1, Student4 o2) {
int num=o1.getTotal()-o2.getTotal();
int num1=num==0?o1.name.compareTo(o2.name):num;
return -num1;
}
});
Scanner scanner = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
System.out.println("输入第" + i + "个学生的信息");
String name = scanner.next();
int math = scanner.nextInt();
int chinese = scanner.nextInt();
int english = scanner.nextInt();
Student4 student4 = new Student4(name, math, chinese, english);
student4s.add(student4);
}
for (Student4 student4 : student4s) {
System.out.println(student4);
}
}
static class Student4 {
private String name;
private int math;
private int chinese;
private int english;
public Student4(String name, int math, int chinese, int english) {
this.name = name;
this.math = math;
this.chinese = chinese;
this.english = english;
}
@Override
public String toString() {
return "Student4{" +
"姓名='" + name +
", 数学=" + math +
", 语文=" + chinese +
", 英语=" + english +",总分="+getTotal()+
'}';
}
public int getTotal(){
return math+chinese+english;
}
}
}