一、Set集合的特点:
无序:存取数据的顺序是不一定的, 当数据存入后, 集合的顺序就固定下来了
不重复:可以去除重复
无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素。
JDKAPI 中所提供的Set集合类常用的有:
HashSet:散列存放(重点)
TreeSet:有序存放(重点)
LinkedHashSet: 有次序
二、HashSet
特点:无序、不重复、无索引。
public static void main(String[] args) {
// 无序, 不重复, 无索引
Set<String> sets = new HashSet<>();
sets.add("MySQL");
sets.add("MySQL");
sets.add("JAVA");
sets.add("JAVA");
sets.add("HTML");
sets.add("HTML");
sets.add("Vue");
sets.add("Vue");
System.out.println(sets);
//输出结果 [JAVA, MySQL, Vue, HTML]
}
三、LinkedSet
根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序
LinkedHashSet集合特点:
底层是一个哈希表(数组+链表/红黑树)+链表,多了一条链表(记录元素的存储顺序),保证元素有序
遍历的时候,LinkedHashSet将会以元素的添加顺序访问集合的元素
LinkedHashSet的方法与它父类HashSet方法是一样的
public static void main(String[] args) {
LinkedHashSet set = new LinkedHashSet();
set.add("hello");
set.add("word");
set.add("zhangsan");
set.add("ls");
set.add("zhangsan");
System.out.println(set);
}
四、TreeSet
特点:排序: 默认升序、不重复、无索引。
注:TreeSet使用红黑树结构对加入的元素进行排序存放,所以放入TreeSet中元素必须是可“排序”的。
public static void main(String[] args) {
// 排序、不重复、无索引
Set<Integer> sets = new TreeSet<>();
sets.add(10);
sets.add(10);
sets.add(20);
sets.add(20);
sets.add(30);
sets.add(30);
sets.add(40);
sets.add(40);
sets.add(50);
sets.add(50);
System.out.println(sets);
// 输出结果 [10, 20, 30, 40, 50]
4.1可排序对象
TreeSet可是采用两种方法实现排序:自然排序和定制排序。默认情况,TreeSet采用自然排序。
TreeSet调用调用集合元素的CompareTo()方法,根据该方法的返回值来比较元素之间的大小,然后进行“升序”排列,这种排序方式我们称之为自然排列。
注意:如果想采用自然排序,则要存储的对象所属类必须实现Comparable 接口。该接口只有一个方法public int compareTo(Object obj),必须实现该方法。
compareTo方法的实现规则:
返回 0,表示 this == obj。//则不会添加新对象
返回正数,表示 this> obj //添加到原来对象的右边
返回负数,表示 this < obj // 添加到原来对的左边
public class Student implements Comparable<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) {
this.name = name;
this.age = age;
}
public Student() {
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Student").append('[')
.append("name=")
.append(name)
.append(",age=")
.append(age)
.append(']');
return sb.toString();
}
@Override
public int compareTo(Student o) {
//根据年龄升序排序
int rs = this.age - o.age;
if(rs == 0 ){
if(o == this){
return 0;
}else{
return -1;
}
}
return rs;
}
}
测试类:
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet treeSet = new TreeSet();
treeSet.add(new Student("张三",21));
treeSet.add(new Student("李四",18));
treeSet.add(new Student("王五",20));
treeSet.add(new Student("李琦",19));
System.out.println(treeSet);
}
}
输出结果为:
4.2定制排序
使用Comparable接口定义排序顺序有局限性:实现此接口的类只能按compareTo()定义的这一种方式排序。
如果需要更加灵活地排序,我们可以自定义(Comparator)比较器,在创建TreeSet集合对象时把我们自定义的比较器传入,则可以TreeSet会按照我们的比较器中定义的规则进行排序。
自定义比较器类,需要实现Comparator接口。Comparator接口只有一个抽象方法需要实现:public int compare(Object a, Object b);
判断规则:
返回 0,表示a == b
返回正数,表示b > b
返回负数,表示a < b
创建TreeSet集合对象时,把自定义比较器对象传入即可,TreeSet会自动按照比较器中的规则进行排序。
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet treeSet = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Student stu1 = (Student)o1;
Student stu2 = (Student)o2;
//按照年龄的降序排序
return stu2.getAge() - stu1.getAge() ;
}
});
treeSet.add(new Student("张三",21));
treeSet.add(new Student("李四",18));
treeSet.add(new Student("王五",20));
treeSet.add(new Student("李琦",19));
System.out.println(treeSet);
}
}
输出结果为: