一、HashSet集合
存储特点:无索引,不可以重复,无序。
无索引、无序:存储结构决定的(树)
不能重复: HashSet在存储元素时,当存储到相同的元素时,这个元素会被剔除。原因:当用HashSet集合存储元素时,会使用add()方法,该方法会从中调用equals方法来判断下次存储的元素是否相同,而equals方法又是根据对象的hashCode来判断的,当存一个元素时,该元素会分配一个hashCode值,当存入下个相同的元素时,会和前面的hashCode值比较,如果相同,则不能存入。
不过在存储自定义对象时,如自定义:student类的对象时,我们认为相同属性的学生为同一个人,但是存储时却不能把相同的学生剔除。因为HashSet在存储对象时,存储的是对象的引用,此时,hashCode值都是不同的。因此,HashSet怎样剔除重复的自定义对象呢?重写hashCode方法,将hashCode值设置为不同的值(默认31)。
LinkedHashSet:底层是用链表实现的,是set集合中唯一一个保证怎么存就怎么取的集合对象, 因为是HashSet的子类,所以也保证了元素的唯一性,与HashSet原理一致 。如果要用Set集合实现有序存储可以用它。
例①:从键盘输入若干个字符,利用Set集合去除字符串中重复的字符
/*
* ①先创建Scanner对象
* ②创建LinkedHashSet对象,将字符存取,去掉重复
* ③将字符串转化为字符数组,存入LinkedHashSet集合中
* */
Scanner sc = new Scanner(System.in);
System.out.print("请输入若干字符:");
LinkedHashSet<Character> lhs = new LinkedHashSet<>();
String s = sc.nextLine();
char []arr = s.toCharArray();
for(char c :arr){
lhs.add(c);
}
System.out.print(lhs);
例②:去除集合中的重复元素
/* 分析:
* 1、创建list集合存储若干个重复元素
* 2、单独定义方法去除元素
* 3、打印list集合
* */
public class TestRemoveRepeat02 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("b");
list.add("c");
System.out.print(getSingle(list));
}
/*去除list集合中的重复元素
*1、创建一个LinkedHashSet集合
* 2、将List集合中所有元素添加到LinkedHashSet集合中
* 3、将list集合清空
* 4、将LinkedHashSet集合中的元素添加会List集合
* */
public static List getSingle(List<String> list){
LinkedHashSet<String> lhs = new LinkedHashSet<>();
/*for(String c :list){
lhs.add(c);
}*/
lhs.addAll(list); //不需要遍历,直接用addAll方法
list.clear(); //将集合清空
list.addAll(lhs);
return list;
}
}
二、TreeSet集合
存储特点:无索引,不可以重复
主要作用: 可以利用它对元素进行排序。因为在调用add()方法存储对象时,会默认调用compareTo方法进行比较,同样也保证了存储的唯一性。不过此外:
当compareTo方法返回零的时候只返回一个元素。(根据存储方式,改元素为树的根节点)
当compareTo方法返回正数的时候,集合会顺序存储。(保存在树的右子树)
当compareTo方法返回负数的时候,集合会倒序存取。(保存在树的左子树)
例①:利用TreeSet集合存储若干个,自定义对象Person(属性有name、age)并根据年龄排序打印出对象。
分析:定一个Personal personal 对象,有name、age属性。因为要根据person.age来判断,默认的compareTo方法定不能满足要求,它只能实现对元素的排序,因此要重写compareTo方法,因此Personal要实现Compare<Personal>接口来实现该功能。
Persnal.java
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 "Person{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
@Override
public int compareTo(Person o) {
int num = this.age-o.age;//年龄是比较的主要条件,姓名为次要条件
return num==0 ? this.name.compareTo(o.name):num;
}
测试类
public class Demo01_TreeSet {
public static void main(String[] args) {
/*TreeSet存储自定义对象*/
TreeSet<Person> ts = new TreeSet<>();
ts.add(new Person("张三",23));
ts.add(new Person("李四",25));
ts.add(new Person("王五",26));
ts.add(new Person("赵六",29));
ts.add(new Person("张三",23));
ts.add(new Person("张3",23));
/*按照年龄排序输出集合*/
System.out.println(ts);
}
例②:在一个集合中存储了无序且重复的字符串,定义一个方法,让其有序(字典排序),且不能去重复
public class Test01 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("aaa");
list.add("cc");
list.add("ddda");
list.add("vvvvaaa");
list.add("ddda");
sort(list);
System.out.print(list);
}
/*
* 定义方法:排序且去重复
* 1、创建TreeSet集合对象,因为TreeSet集合本身具备比较功能
* 2、将List集合中的所有元素添加到TreeSet集合中,对其排序,保留重复
* 3、清空List集合
* 4、将TreeSet集合排好序的集合添加至List集合中
* */
public static void sort(List<String> list){
/*因为用TreeSet集合排序要去重复,因此我们必须重写它的compareTo方法来完成我们想要的功能
* 我们采取匿名内部类的方式实现
* */
TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
int num = s1.compareTo(s2);//比较内容为主要条件
return num == 0 ? 1 : num;//当两个字符串一样时,我们把compare的值设置为1,使其保存
}
});
ts.addAll(list);
list.clear();
list.addAll(ts);
}
}
例③:可以从键盘输入多个整数,查到输入quit时结束输入。把所有输入的数倒序排列输出
/* 可以从键盘输入多个整数,查到输入quit时结束输入。把所有输入的数倒序排列输出
* 1、创建scanner对象
* 2、创建TreeSet集合对象,TreeSet集合中传入比较器
* 3、不断的接受整数,遇到quit退出.因为退出为quit,所以键盘录入时都以字符串的形式录取
* 4、判断是quit退出,不是转化为Integer,添加到集合中
* 5、遍历TreeSet集合
* */
public class Test03 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入数字,回车键为间隔:");
TreeSet<Integer> ts = new TreeSet<>(new Comparator<Integer>() {
@Override
public int compare(Integer i1, Integer i2) {
int num = i2-i1;
return num == 0 ? 1 : num;
}
});
while(true){
String line = sc.nextLine();
if("quit".equals(line)){
break;
}
try {
Integer integer = Integer.parseInt(line);
ts.add(integer);
}catch (Exception e){
System.out.println("请输入数字!");
}
}
for(Integer i : ts){
System.out.println(i);
}
}
}