目录
1.Set集合的特点
不可重复
无序(无下标)
2.set集合遍历方式
foreach遍历
迭代器iterator遍历
3.Set集合去重
展示柜中不重复展示相同物品
4.set集合自然排序和比较器排序
Set集合自然排序
Set集合比较器排序
本篇内容思维导图:
1.Set集合的特点
不可重复
先看以下代码:
Set<Object> set=new HashSet<>();
set.add("b");
set.add("c");
set.add("a");
set.add("b");
运行结果输出固定为a,b,c
不会出现两个b,说明set不可重复
无序(无下标)
2.set集合遍历方式
foreach遍历
for (Object o : set) {
System.out.println(o);
}
迭代器iterator遍历
Iterator<Object> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
3.Set集合去重
原理: hashset底层数据结构是哈希表, 优先会调用hashcode方法对比地址,然后调用equals方法对比值
运行如下代码:
public class Demo1 {
public static void main(String[] args) {
Set<Object> set = new HashSet<>();
set.add(new Student("dmz", 16));
set.add(new Student("wyf", 36));
set.add(new Student("hpw", 26));
set.add(new Student("wyf", 36));
for (Object o : set) {
System.out.println(o);
}
}
}
class Student {
private String name;
private int 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;
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
控制台输出为:
Student [name=dmz, age=16]
Student [name=wyf, age=36]
Student [name=hpw, age=26]
Student [name=wyf, age=36]
出现了相同的两条数据,说明并没有实现去重
重写hashCode方法,代码如下
public class Demo2 {
public static void main(String[] args) {
Set<Object> set = new HashSet<>();
set.add(new Students("dmz", 16));
set.add(new Students("wyf", 36));
set.add(new Students("hpw", 26));
set.add(new Students("wyf", 36));
for (Object o : set) {
System.out.println(o);
}
}
}
class Students {
private String name;
private int 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;
}
public Students(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int hashCode() {
System.out.println("hashCode方法被调用");
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
System.out.println("equals方法被调用");
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Students other = (Students) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
控制台输出为:
hashCode方法被调用
hashCode方法被调用
hashCode方法被调用
hashCode方法被调用
equals方法被调用
Student [name=wyf, age=36]
Student [name=dmz, age=16]
Student [name=hpw, age=26]
hashCode方法被调用四次
因为每new一次students,就调用一次hashCode方法生成地址
equals方法被调用一次
因为当遇到相同地址时,调用equals方法比较内容是否相同
将hashcode方法返回0:
@Override
public int hashCode() {
System.out.println("hashCode方法被调用");
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return 0;
}控制台输出为:
hashCode方法被调用 //生成第一条数据的地址
hashCode方法被调用 //生成第二条数据的地址
equals方法被调用 //将第二条数据的内容与第一条数据的内容比较
hashCode方法被调用 //生成第三条数据的地址
equals方法被调用 //将第三条数据的内容与第一条数据的内容比较
equals方法被调用 //将第三条数据的内容与第二条数据的内容比较
hashCode方法被调用 //生成第四条数据的地址
equals方法被调用 //将第四条数据的内容与第一条数据的内容比较
equals方法被调用 //将第四条数据的内容与第二条数据的内容比较,相同,故不再调 用第三次equals方法
Student [name=dmz, age=16]
Student [name=wyf, age=36]
Student [name=hpw, age=26]
我们可以这样理解:
set集合为商品展示柜台
一个物品放在一个专属展示柜进行展示
展示柜中不重复展示相同物品
4.set集合自然排序和比较器排序
Set集合自然排序
public class Demo3 {
public static void main(String[] args) {
Set<User> set=new TreeSet<>();
set.add(new User("zs", 1800));
set.add(new User("ls", 800));
set.add(new User("ww", 900));
set.add(new User("zl", 1200));
for (User user : set) {
System.out.println(user);
}
}
}
class User{
private String name;
private int money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public User(String name, int money) {
super();
this.name = name;
this.money = money;
}
@Override
public String toString() {
return "User [name=" + name + ", money=" + money + "]";
}
}
控制台输出会报错: com.ltf.User cannot be cast to java.lang.Comparable
类型转换异常,user需要实现Comparable接口
Comparable接口:对实现它的每个类的对象进行整体排序,即该类的自然排序
compareTo:该类的自然比较方法
同理: Object s=new Students("zz", 12);
User u=(User)s;//强转,编译不报错,运行报错User implements Comparable
@Override
public int compareTo(Object o) {//自然比较方法
// TODO Auto-generated method stub
return 0;
}
将money由低到高排序和由高到低排序
public class Demo3 {
public static void main(String[] args) {
Set<User> set=new TreeSet<>();
set.add(new User("zs", 1800));
set.add(new User("ls", 800));
set.add(new User("ww", 900));
set.add(new User("zl", 1200));
for (User user : set) {
System.out.println(user);
}
}
}
class User implements Comparable{//继承comparable接口
private String name;
private int money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public User(String name, int money) {
super();
this.name = name;
this.money = money;
}
@Override
public String toString() {
return "User [name=" + name + ", money=" + money + "]";
}
@Override
public int compareTo(Object o) {//user类的自然比较方法,o为要对比的值
User u=(User)o;
return this.money-u.money;//money由低到高排列
//return -money-this.money;//money由高到低排列
}
}
Set集合比较器排序
因为不同的模块有不同的需求,对于一张表有不同的排序规则,这个时候就要用到比较器进行排序
代码如下:
class MoneyAsc implements Comparator<User>{
@Override
public int compare(User o1, User o2) {
// TODO Auto-generated method stub
return o1.getMoney()-o2.getMoney();// money由低到高排列
}
}
也可以像下面这样写:
Set<User> set = new TreeSet<>(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
// TODO Auto-generated method stub
return (((User)o1).getMoney()-((User)o2).getMoney());
}
});
还可根据名字首字母排序a-z:
Set<User> set = new TreeSet<>(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
// // TODO Auto-generated method stub
// return (((User)o1).getMoney()-((User)o2).getMoney());
String name1=((User)o1).getName();
String name2=((User)o2).getName();
return name.comparaTo(name2);
}
});