一、Set接口
1.1 特点
- Set不可重复
- 存储顺序不一致
- 没有带索引的方法,所有不能使用普通for循环,也不能通过索引来获取,删除Set集合里面的元素
public class SetDemo {
public static void main(String[] args) {
Set<String> set = new TreeSet<>();
set.add("ddd");
set.add("aaa");
set.add("aaa");
set.add("bbb");
set.add("ccc");
for (String s : set) {
System.out.println(s);
}
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
1.1.1 常用方法
- boolean add(Object o):该方法用于向集合里添加一个元素。
- boolean addAll(Collection c):该方法把集合c里的所有元素添加到指定集合里。
- void clear():清除集合里的所有元素,将集合长度变为0。
- boolean contains(Object o):返回集合里是否包含指定元素。
- boolean containsAll(Collection c):返回集合里是否包含集合c里的所有元素。
- boolean isEmpty():返回集合是否为空。当集合长度为0时返回true,否则返回false。
- Iterator iterator():返回一个Iterator对象,用于遍历集合里的元素。
- boolean remove(Object o):删除集合中的指定元素o,当集合中包含了一个或多个元素o时,这些元素将被删除,该方法将返回true。
- boolean removeAll(Collection c):将集合中删除集合c里包含的所有元素(相当于用调用该方法的集合减集合c),如果删除了一个或一个以上的元素,则该方法返回true。
- boolean retainAll(Collection c):将集合中删除集合c里不包含的元素(相当于把调用该方法的集合变成该集合的集合c的交集),如果该操作改变了调用该方法的集合,则该方法返回true。
- int size():该方法返回集合里元素的个数。
- Object[] toArray():该方法把集合转换成一个数组,所有的集合元素变成对应的数组元素
1.2 实现类
- HashSet
- TreeSet
1.2.1 HashSet
1.2.1.1 特定
- 底层数据结构是哈希表
- 不能保证存储和取出的顺序完全一致
- 没有带索引方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以元素唯一
public class HashSetDemo1 {
public static void main(String[] args) {
HashSet<String> hs = new HashSet<>();
hs.add("Hello");
hs.add("World");
hs.add("Java");
hs.add("Java");
hs.add("Html");
hs.add("CSS");
hs.add("JS");
Iterator<String> iterator = hs.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
for (String h : hs) {
System.out.println(h);
}
}
}
哈希值
哈希值(哈希码值):是JDK根据对象的地址或者属性,算出来的int类型的整数
注:Object类中有一个方法可以获取对象的哈希值
public int hasCode()
:根据对象的地址值计算出来的哈希值
特点
- 如果没有重写hasCode方法,那么是根据对象的地址址计算出的哈希值,同一个对象多次调用hasCode()方法返回的哈希值是相同的,不同对象的哈希值是不一样的。
- 如果重写了hasCode方法,一般都是通过对象的属性值计算出哈希值。如果不同的对象属性值是一样的,那么计算出来的的哈希值也是一样的。
Java底层实现
- JDK8之前,底层采用数组+链表实现。
- JDK8以后,底层进行了优化。由数组+链表+红黑树实现。
注:如果HashSet集合要存储自定义对象,那么必须重写hasCode和equals方法。
1.2.2 TreeSet
1.2.2.1 特定
- 不包含重复元素的集合
- 没有带索引的方法
- 可以将元素按照规则进行排序
- 想要使用TreeSet存储自定义对象,需要制定排序规则
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Integer> ts = new TreeSet<>();
ts.add(5);
ts.add(3);
ts.add(4);
ts.add(1);
ts.add(2);
System.out.println(ts); // [1, 2, 3, 4, 5]
}
}
1.2.2.2 自然排序Comparable的使用
- 使用空参构造创建TreeSet集合
- 自定义的Student类实现Comparable接口
- 重写里面的comparaTo方法
原理
- 如果重写的方法返回值为负数,表示当前存入的元素是较小值,存左边
- 如果返回值为0,表示当前存入的元素跟集合中元素重复了,不存
- 如果重写的方法返回值为正数,表示当前存入的元素是较大值,存右边
public class Person implements Comparable<Person> {
private String name;
private int age;
public Person() {
}
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 "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Person o) {
// 按照对象的年龄进行排序,年龄一样在按照姓名排序,
int result = this.age - o.age;
result = result == 0? this.name.compareTo(o.getName()) : result;
return result;
}
}
public class TreeSetDemo2 {
public static void main(String[] args) {
TreeSet<Person> treeSet = new TreeSet<>();
Person s1 = new Person("张",15);
Person s2 = new Person("李",30);
Person s3 = new Person("王",20);
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
System.out.println(treeSet); // [Person{name='张三', age=15}, Person{name='王五', age=20}, Person{name='李四', age=30}]
}
}
比较器排序Comparator的使用
- TreeSet的带参构造方法使用的是比较器排序对元素进行排序的
- 比较器排序,就是让集合构造方法接收Cpmparator的实现类对象,重写compareTo(T o1,T o2)方法
- 重写方法的时候,一定要注意排序规则必须按照要求的主要条件和次要条件来写
public class TreeSetDemo4 {
public static void main(String[] args) {
TreeSet<Teacher> treeSet = new TreeSet<>(new Comparator<Teacher>() {
@Override
public int compare(Teacher o1, Teacher o2) {
// 主要条件
int result = o1.getAge() - o2.getAge();
// 次要条件
result = result == 0 ? o1.getName().compareTo(o2.getName()):result;
return result;
}
});
Teacher t1 = new Teacher("zhangsan",23);
Teacher t2 = new Teacher("lisi",23);
Teacher t3 = new Teacher("wangwu",40);
treeSet.add(t1);
treeSet.add(t2);
treeSet.add(t3);
System.out.println(treeSet);
}
}
public class Teacher {
private String name;
private int age;
public Teacher() {
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Teacher(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;
}
}
注:在使用的时候,默认使用自然排序,当自然排序不满足现在的需求,使用比较器排序