文章目录
1.Set接口
Set接口与List接口最大的区别就是Set不允许存放重复元素,Set接口并没有对Collection接口进行扩充,而List对Collection进行了扩充。因此,在Set接口中没有get()、set()方法。
在Set子接口中有两个常用子类:HashSet(无序存储)、TreeSet(有序存储)
1.1 HashSet类
产生版本:JDK1.2
包:java.util.HashSet
定义:HashSet<E> hashSet = new HashSet<>(); Set<String> hashSet = new HashSet<>();
import java.util.HashSet;
public class Test {
public static void main(String[] args) {
HashSet<String> hashSet = new HashSet<>();
hashSet.add("hello");
hashSet.add("world");
hashSet.add("A");
hashSet.add("C");
hashSet.add("D");
hashSet.add("y");
//1.允许存放空值
hashSet.add(null);
//2.添加重复元素
hashSet.add("A");
//3.输出集合的长度
System.out.println(hashSet.size());
//输出集合
System.out.println(hashSet);
//4.集合中是否包含a
System.out.println(hashSet.contains("a"));
//5.删除A
System.out.println(hashSet.remove("A"));
System.out.println(hashSet);
}
}
运行结果:
7
[null, A, world, C, D, y, hello]
false
true
[null, world, C, D, y, hello]
HashSet不允许元素重复、 无序存储(根据哈希码保存)、可以存放空值、底层基于哈希表
1.2 TreeSet类
import java.util.TreeSet;
public class Test{
public static void main(String[] args) {
TreeSet<Integer> treeSet = new TreeSet<>();
treeSet.add(1);
treeSet.add(2);
treeSet.add(9);
treeSet.add(6);
treeSet.add(4);
//1.添加重复元素
treeSet.add(2);
//2.输出集合的长度
System.out.println(treeSet.size());
//3.集合中是否包含pig
System.out.println(treeSet.contains(2));
System.out.println(treeSet);
//4.删除pig
System.out.println(treeSet.remove(2));
System.out.println(treeSet);
}
}
TreeSet不可以存放重复元素、按升序存放、不允许存放null(否则会有空指针异常)、底层基于红黑树
1.3 TreeSet排序
TreeSet对于自定义的类不支持排序,那么有什么排序方式呢?
第一种方式:实现可比较接口Comparable覆写compareTo方法
第一种方式:Treeset构造方法传入比较器接口实现类的对象
1.3.1 实现Comparable接口
import java.util.Set;
import java.util.TreeSet;
class Person implements Comparable<Person>{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person o) {
//升序
return this.age - o.age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) {
Person per1 = new Person("王五",19);
Person per2 = new Person("张三",88);
Person per3 = new Person("李四",2);
Set<Person> set = new TreeSet<>();
set.add(per1);
set.add(per2);
set.add(per3);
for(Person person:set){
System.out.println(person);
}
}
}
运行结果:
Person{name=‘李四’, age=2}
Person{name=‘王五’, age=19}
Person{name=‘张三’, age=88}
1.3.2 构造方法传入比较器接口实现类的对象
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
class Person {
private String name;
private int age;
public Person(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 "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) {
Person per1 = new Person("王五",19);
Person per2 = new Person("张三",88);
Person per3 = new Person("李四",2);
//匿名内部类
Set<Person> set = new TreeSet<>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();
}
});
set.add(per1);
set.add(per2);
set.add(per3);
for(Person person:set){
System.out.println(person);
}
}
}
运行结果:
Person{name=‘李四’, age=2}
Person{name=‘王五’, age=19}
Person{name=‘张三’, age=88}
1.3.3 排序总结
关于TreeSet排序总结:
- 实现Comparable接口 -----内部排序
- 通过构造方法传入Comparator接口对象----外部排序
- 如果这两种方式都在,优先使用Comparator外部排序接口
1.4 重复元素判断
用TreeSet子类进行数据保存的时候,重复元素的判断依靠的是ComParable接口完成的,但是这并不是全部Set接口判断重复元素的方式,因为如果使用的是HashSet子类,由于其跟Copmarable没有任何关系,所以它判断重复元素的方式依靠的是Object类中的两个方法:
hash码:public native int hashCode();
对象比较:public poolean equals(Object obj);
在Java中进行对象比较的步骤:
通过一个对象的唯一编码找到一个对象的信息,当编码匹配之后载调用equals方法进行内容的比较
import java.util.Comparator;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.HashSet;
import java.util.Set;
class Person {
private String name;
private Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//覆写equals和hashcode方法时,比较内容参与的属性也要参与hashcode计算
@Override
public boolean equals(Object o) {
//1.如果要比较的两个对象的地址相等直接返回true
if(this == o){
return true;
}
//2.判断要比较的对象是不是Person类的实例 如果不是 直接返回false
if(o instanceof Person){
//如果要判断的对象是Person类的实例 向上转型比较属性
Person per = (Person)o;
return this.name.equals(per.name)&&
this.age==per.age;
}
return false;
}
@Override
public int hashCode() {
int h = this.age.hashCode();
h = h*31+this.name.hashCode();
return h;
}
}
public class Test {
public static void main(String[] args) {
Person per1 = new Person("王五",19);
Person per2 = new Person("张三",88);
Person per3 = new Person("李四",2);
Person per4 = new Person("李四",2);
//匿名内部类
Set<Person> set = new HashSet<>();
set.add(per1);
set.add(per2);
set.add(per3);
set.add(per4);
System.out.println(set.size());
System.out.println(set);
}
}
运行结果:
3
[Person{name=‘李四’, age=2}, Person{name=‘王五’, age=19}, Person{name=‘张三’, age=88}]