一,Set集合的特点
1.无重复,无序(基本数据类型&String才会自动去重)
二,Set集合遍历方式
因为Set集合中没有下标,只能用foreach 以及 迭代器 两种方式输出
1.增强for循环 foreach
2.迭代器
package com.ljj.set;
import java.util.HashSet;
import java.util.Iterator;
/**
* set集合的特点
* 不重复:基本数据类型&String
* @author Administrator 刘俊杰
*下午4:37:45
*/
public class Demo1 {
public static void main(String[] args) {
HashSet<Object> set = new HashSet<>();
set.add("zs");
set.add("ls");
set.add("ww");
set.add("老六");
set.add("ls");
System.out.println(set.size());
System.out.println("---------------foreach循环-----------");
for (Object obj : set) {
System.out.println(obj);
}
System.out.println("---------------迭代器--------------");
Iterator<Object> it=set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
运行结果:
三,HashSet哈希表存储,底层去重原理
案例1,将一个set集合去重,去除name值相同的对象
实体类 以及 已存入对象的set集合:
package com.ljj.set;
import java.util.HashSet;
/**
* set底层去重原理
* 1.set去重底层原理是对象的hashCode方法以及equals方法相关
* 2.判断重复元素的时候,是比较hashCode值,在调用equals比较内容
* @author Administrator 刘俊杰
*下午4:47:55
*/
public class Demo2 {
public static void main(String[] args) {
HashSet<Object> set = new HashSet<>();
set.add(new Person("ws",18,1));
set.add(new Person("zh",18,2));//distrinct
set.add(new Person("ls",85,3));
set.add(new Person("老六",8,4));
set.add(new Person("zh",18,1));
System.out.println(set.size());
}
}
class Person{
private String name;//姓名
private int age;//年龄
private int dj;//等级
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 int getDj() {
return dj;
}
public void setDj(int dj) {
this.dj = dj;
}
public Person() {
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", dj=" + dj + "]";
}
public Person(String name, int age, int dj) {
super();
this.name = name;
this.age = age;
this.dj = dj;
}
}
打印出set集合的长度:5
因为Set中存的值为对象,不是基本数据类型以及String 所以无法自动去重
方法:重写HashCode以及equals方法
private String name;//姓名
private int age;//年龄
private int dj;//等级
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 int getDj() {
return dj;
}
public void setDj(int dj) {
this.dj = dj;
}
public Person() {
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", dj=" + dj + "]";
}
public Person(String name, int age, int dj) {
super();
this.name = name;
this.age = age;
this.dj = dj;
}
//重写
@Override
public int hashCode() {
System.out.println("=============hashCode============");
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + dj;
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;
Person other = (Person) obj;
if (age != other.age)
return false;
if (dj != other.dj)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
再次打印结果为:
结论:
1.不是默认数据类型以及String类型时 去重需要重写hashCode以及equals方法
2.Set去重底层原理是与对象的hashCode以及equals方法相关
3.判断重复元素时,先比较hashCode值,再调用equlas比较内容
四,TreeSet(自然排序,比较器排序)
案例2:根据用户的级别进行会议座位的排序
实体类erson:
class Person{ private String name;//姓名 private int age;//年龄 private int dj;//等级 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 int getDj() { return dj; } public void setDj(int dj) { this.dj = dj; } public Person() { // TODO Auto-generated constructor stub } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", dj=" + dj + "]"; } public Person(String name, int age, int dj) { super(); this.name = name; this.age = age; this.dj = dj; } }
TreeSet集合:
package com.ljj.set;
import java.util.Comparator;
import java.util.TreeSet;
/**
* set集合排序
* java.lang.Comparable,自然排序 排序的规则是单一的,不能够应对复杂的变化的需求
* java.util.comparator, 比较级排序
* @author Administrator 刘俊杰
*下午5:49:31
*/
public class Demo3 {
public static void main(String[] args) {
TreeSet set = new TreeSet<>();
set.add(new Person("zs",18,1));
set.add(new Person("ls",24,4));
set.add(new Person("ww",26,2));
set.add(new Person("laoliu",28,3));
set.add(new Person("zs",18,3));
for (Object obj : set) {
System.out.println(obj);
}
}
运行结果:Comparable 类型转化异常
原因:
之前的String类型之所以可以转换无误是因为实现了Comparable接口,而我们自定义的person对象却没有
解决方法:
把自定义的person类实现Comparable接口,并实现compareTo方法
class Person implements Comparable<Person>{
private String name;//姓名
private int age;//年龄
private int dj;//等级
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 int getDj() {
return dj;
}
public void setDj(int dj) {
this.dj = dj;
}
public Person() {
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", dj=" + dj + "]";
}
public Person(String name, int age, int dj) {
super();
this.name = name;
this.age = age;
this.dj = dj;
}
/**
* 实现方法
*/
@Override
public int compareTo(Person o) {
return this.dj -o.getDj();
}
}
再次运行结果:(成功排序!)
案例3:在案例一的基础上 按照年龄升序再次进行排序
TreeSet集合以及运行结果:
从集合中可以看到其中包含了两个年龄相同的对象,一共五条数据,但是结果只有四条,说明此时发生了数据丢失的现象
原因:
运行进行了判断,当属性值相同时,进行了自动去重
所以我们要手动对第二个值进行判断
解决方法:将compareTo方法为:
此时运行结果:(成功)
案例4:按照姓名首拼音首字母进行升序排序
从前两个案例中发现我们要排序 修改的一直是compareTo方法,使用Comparable接口,也就是自然排序,这种方法太单一,并且太受限制,无法满足更多的复杂的编码需求
这时候就需要使用到我们的第二种方法:实现Comparator接口(比较器排序)
首先,在实例化TreeSet时选择实现Comparator接口
其次,在定义实例化的地方加上比较器来比较首字母
***比较器器代码写错则无效
运行结果:(成功按字母排序)
我们再用比较器排序来完成案例3
操作:在编辑比较器的时候添加条件的判断即可
TreeSet<Person> set = new TreeSet<>((x,y)-> {
int ageRes = x.getAge() - y.getAge();
int djRes=0;
if(ageRes==0) {
djRes=x.getDj() - y.getDj();
}else {
return ageRes;
}
return djRes;
});
set.add(new Person("zs",18,1));
set.add(new Person("ls",24,4));
set.add(new Person("ww",26,2));
set.add(new Person("laoliu",28,3));
set.add(new Person("sdf",23,4));
for (Object obj : set) {
System.out.println(obj);
}
}
运行结果:(成功)