Java SE—集合类中的Set
一.HashSet的使用
1. HashSet存储字符串并遍历
package PPP;
import java.util.HashSet;
public class Entrance {
public static void main(String[] args) {
//HashSet不允许有相同的元素
HashSet<String> a=new HashSet();
//add(); 每次添加元素调用当前元素的equals方法如果返回true则添加失败false反之
boolean b1=a.add("China");
boolean b2=a.add("China1");
boolean b3=a.add("China");
System.out.println(b1);
System.out.println(b2);
System.out.println(b3);
//换一种方式添加String类型对象
HashSet<String> a=new HashSet();
//在String的jdk里equals方法被复写只要”字符串“内容是一样的就为相同元素
boolean b1=a.add(new String("China"));
boolean b2=a.add(new String("China"));
System.out.println(b1);
System.out.println(b2);
}
}
二.HashSet存储自定义对象保证元素唯一性
1.HashSet原理
a.我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
b.当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象
b1.如果没有哈希值相同的对象就直接存入集合
b2.如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存
推断:
1 hashCode()方法返回的值不同,则一定不是同一个对象
2.hashCode()方法返回的值相同,则不一定是同一个对象
3.equals方法返回值不同,是不同对象,返回值相同是同一个对象。
(前提是这些方法都没有被复写继承的是Object的方法)
三.Treeset的使用
1.案例演示:存储Person对象并按照年龄大小排列
第一种方式实现Comparable接口
package PPP;
import java.util.TreeSet;
public class Entrance {
public static void main(String[] args) {
TreeSet<Person> a=new TreeSet<>();
//在String的jdk里equals方法被复写只要”字符串“内容是一样的就为相同元素
boolean b1=a.add(new Person(88));
boolean b2=a.add(new Person(99));
boolean b3=a.add(new Person(77));
boolean b4=a.add(new Person(66));
boolean b7=a.add(new Person(66));
for(Person unit:a){
System.out.println(unit.age);
}
System.out.println(b1);
System.out.println(b2);
}
}
class Person implements Comparable{
int age;
Person(int age){
this.age=age;
}
//重写compare方法
@Override
public int compareTo(Object o) {
Person p=(Person) o;
//建树的过程:p.age为最上层的数字 相减结果大于0则在树的右边 等于0:相等(无法被添加进来) 小于0:在树的左边
return this.age-p.age;//从小到大排列
return -(this.age-p.age);//从大到小排列
}
}
第二种实现Comparator方式
package PPP;
import java.util.Comparator;
import java.util.TreeSet;
public class Entrance {
public static void main(String[] args) {
//将写有标准的对象B写入到构造函数种,Person类就不用实现Comparator接口
//如果Person类实现了Compare接口,B类实现了Comparator接口 优先按照Comparator接口来写
TreeSet<Person> a=new TreeSet<>(new B());
//在String的jdk里equals方法被复写只要”字符串“内容是一样的就为相同元素
boolean b1=a.add(new Person(88));
boolean b2=a.add(new Person(99));
boolean b3=a.add(new Person(77));
boolean b4=a.add(new Person(66));
boolean b7=a.add(new Person(66));
for(Person unit:a){
System.out.println(unit.age);
}
System.out.println(b1);
System.out.println(b2);
}
}
class Person {
int age;
Person(int age){
this.age=age;
}
}
//另外定义一个类去写“标准”
class B implements Comparator{
// o1是标准数字不可变的 o2是可变的最上层数字
@Override
public int compare(Object o1, Object o2) {
Person p1 =(Person) o1;
Person p2 =(Person) o2;
return p1.age-p2.age; //从小到大排列
}
}
总结:不管用哪种方式去写其实都是去定义一个“标准”然后按照我们标准的顺序去排列这也就是TreeSet的优点。
四.俩种方式的区别
1.TreeSet构造函数什么都不传,但是Person类要实现Comparable接口
2.TreeSet构造函数需要传一个写有标准的类的对象,但是Person类不要实现 Comparable接口
3. TreeSet如果传入Comparator,Person类又实现了Comparable接口
就优先按照Comparator