Collection:存储单列数据
List:有序可重复
Set:无序不可重复(不是按照插入顺序输出的)
Set接口是Collection子接口,set没有提供额外的方法
HashSet :是set接口的典型实现类,大多数使用set即可的时候,都会选择该类
今天要学习的内容:红色划线的部分
Hashset底层是:数组+链表
底层也是有数组的,初始长度为16;
当使用率超过原来的0.75倍的时候就去扩容,0.75*16=12,超过12的时候就去扩容,扩容两倍;16–32—64
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
public class SetDemo01 {
public static void main(String[] args) {
Set hs=new HashSet();
hs.add("小智");
hs.add("iu");
hs.add("海子");
System.out.println(hs.add("iu"));//数据重复,插入失败
System.out.println(hs);
HashSet<Student> hs1=new HashSet();
hs1.add(new Student("小泽川",16));
/*
当向集合中添加小泽川这名学生对象的时候,
先去调用'小泽川'学生对象所在类的hashCode方法,计算出当前对象的hash值
此时hash值经过某种算法,算出该元素在hashSet底层数组存储的下标(索引)
如果该下标处没有元素,则此时'小泽川'添加成功
*/
hs1.add(new Student("小波比",18));
/*
前提'小泽川'和'小波比'两个对象通过某种特定算法得出的下标一致
当'小泽川'添加成功后,再添加'小波比'我们就会发现指定的下标处有元素'小泽'
当发现下标元素相同的元素时,需要判断两个对象是否同一个对象,如果是添加失败,反之添加成功
1.比较两个元素的hash值
如何hash值不相同,则元素添加成功
如果hash值相同,则通过equals比较两个对象
2.比较两个元素的equals方法
如果equals方法返回false,则'小波比'添加成功
如果equals方法返回true,则'小波比'添加失败
*/
hs1.add(new Student("小苍梧",17));
/*
LinkedHashSet是HashSet的子类:
LinkedHashSet他使用双向链表来维护元素的顺序
使得元素看起来是按照插入顺序保存的
*/
Set hs2=new LinkedHashSet();
hs2.add("小智");
hs2.add("iu");
hs2.add("海子");
System.out.println(hs2);
}
}
class Student{
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
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 == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
TreeSet是SortedSet,SortedSet是Set的子接口(查询速度比List还快,底层是2叉树)
自然排序:
import java.util.TreeSet;
public class SetDemo02 {
public static void main(String[] args) {
TreeSet set1=new TreeSet();
set1.add("777");
set1.add("333");
set1.add("111");
set1.add("222");
System.out.println(set1);
TreeSet<Student> set2=new TreeSet();
set2.add(new Student("333",18));
set2.add(new Student("333",19));
set2.add(new Student("333",17));
System.out.println(set2);
}
}
//连接接口Comparable
class Student implements Comparable{
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
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 == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
/*
重写compareTo方法
需要学生按照什么顺序排序
根据名字或这年龄
this当前对象:o对象
*/
@Override
public int compareTo(Object o) {
if (o instanceof Student) {
//o能转为学生类,则比较内容
//1.将o强转为Student
Student s = (Student) o;
//2.如果按照名字排序
//默认升序
//return this.name.compareTo(s.name);
//return -this.name.compareTo(s.name);//降序
//3.如果只根据年龄排序
//return Integer.compare(this.age,s.age);
//4.如果先根据名字,在根据年龄排序
int num = this.name.compareTo(s.name);
if (num == 0) {//判断名字比较结果是否为0;如果为0则表示名字相同,这样才会比较年龄
return -Integer.compare(this.age, s.age);
}else{
return num;
}
} else {
//o不能转为学生类,则不需要比较
throw new RuntimeException("类型不匹配,无法比较");
}
}
}
定制排序:Comparator
import java.util.Comparator;
import java.util.TreeSet;
public class SetDemo03 {
public static void main(String[] args) {
//1.使用匿名内部类创建Comparator实例
Comparator c1=new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof String && o2 instanceof String){
String s1=(String)o1;
String s2=(String)o2;
return -s1.compareTo(s2);
}
return 0;
}
};
//需要将上述定制排序的实例传入TreeSet
TreeSet set1=new TreeSet(c1);
set1.add("777");
set1.add("333");
set1.add("111");
set1.add("222");
System.out.println(set1);
}
}
小案例
1.创建麻将对象
1.花色 color
2.字符 num
3.每个数字牌对应的个数,方便后面比对,这里使用字符串 index
分别使用定制排序,或者自然排序;对插入的五个麻将对象(自行随机插入五个)进行排序
定制排序使用按照花色升序和字符排序升序
自然排序按照花色降序和字符降序
代码如下:
package work.day0302;
import java.util.Objects;
public class mahjong implements Comparable{
private String color;
private int num;
private int index;
public mahjong() {
}
public mahjong(String color, int num, int index) {
this.color = color;
this.num = num;
this.index = index;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
@Override
public String toString() {
return "mahjong{" +
"color='" + color + '\'' +
", num=" + num +
", index=" + index +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
mahjong mahjong = (mahjong) o;
return num == mahjong.num &&
index == mahjong.index &&
Objects.equals(color, mahjong.color);
}
@Override
public int hashCode() {
return Objects.hash(color, num, index);
}
//自然排序:按照我的需求排序
@Override
public int compareTo(Object o) {
if (o instanceof mahjong){
mahjong m=(mahjong)o;
//先判断花色
int num1=-this.color.compareTo(m.color);
if (num1==0){
//花色相同,判断数值
return -Integer.compare(this.num,m.num);
}else{
return num1;
}
}else{
throw new RuntimeException("类型不匹配");
}
}
}
针对上述类,做的一个自然排序测试类
package work.day0302;
import java.util.TreeSet;
//自然排序
public class Test2 {
public static void main(String[] args) {
TreeSet<mahjong> t=new TreeSet();
t.add(new mahjong("筒",3,1));
t.add(new mahjong("筒",1,1));
t.add(new mahjong("条",3,1));
t.add(new mahjong("万",9,1));
t.add(new mahjong("筒",4,1));
System.out.println(t);
}
}
package work.day0302;
import java.util.Comparator;
import java.util.TreeSet;
public class Test1 {
public static void main(String[] args) {
Comparator c=new Comparator() {
@Override
public int compare(Object o1, Object o2) {
//判断
if (o1 instanceof mahjong && o2 instanceof mahjong){
mahjong m1=(mahjong)o1;
mahjong m2=(mahjong)o2;
int num=m1.getColor().compareTo(m2.getColor());
if (num==0){
return Integer.compare(m1.getNum(),m2.getNum());
}else{
return m1.getColor().compareTo(m2.getColor());
}
}else{
throw new RuntimeException("类型不匹配");
}
}
};
TreeSet<mahjong> t=new TreeSet(c);
t.add(new mahjong("筒",3,1));
t.add(new mahjong("筒",1,1));
t.add(new mahjong("条",3,1));
t.add(new mahjong("万",9,1));
t.add(new mahjong("筒",4,1));
System.out.println(t);
}
}