一.Set集合
特点:无序(没有下标) 不重复
这里对有序的定义是:按什么顺序存储 打印出来还是什么顺序
1.HashSet:去重的功能
example:无序:
//创建一个HashSet
//保存 f f a a b b d d
HashSet<String> set = new HashSet<>();
set.add("q");
set.add("q");
set.add("w");
set.add("w");
set.add("e");
set.add("e");
set.add("r");
set.add("r");
//迭代器遍历
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
String next = iterator.next();
System.out.println(next);
}
//增强for循环
for (String string : set) {
System.out.println(string);
}
结果说明HashSet集合是无序的:
了解HashSet是怎么去重的:
//创建Set集合 保存六个人 两两重复
HashSet<Person> set = new HashSet<>();
set.add(new Person("小风",13));
set.add(new Person("小风",13));
set.add(new Person("张三",18));
set.add(new Person("张三",18));
set.add(new Person("李四",20));
set.add(new Person("李四",20));
//遍历集合
for (Person person : set) {
System.out.println(person);
}
需要在Person类中重写equals方法和hashCode方法
先重写equals方法 发现equals方法未被调用
@Override
public boolean equals(Object obj) {
Person person = (Person)obj;
System.out.println("调用equals方法");
return this.age == person.getAge() &&
this.name.equals(person.getName());
}
然后重写hashCode方法:
@Override
public int hashCode() {
System.out.println("精神可嘉阿迪吉萨");
//返回一个固定值 让所有创建出来的Person对象 HashCode码都一样
//返回固定值效率不高(equals每次都会被调用)
return 10;
//当添加到set中的对象 HashCode码不相同时,没有调用equals方法
//并且对象直接存到set集合中
//HashCode码相同时,会调用equals方法来查看是否是同一个对象,是就不存进去,不是就存进去
}
这时才会调用equals方法
因为只要创建对象就会给每一个对象分配一个HashCode码 当HashCode码相同时才会调用equals方法
看一下用系统直接生成的重写equals方法和hashCode方法:
@Override
public int hashCode() {
//复杂度 是为了减少hashcode码重复
//提高存储时候调用equals方法的效率
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)//如果两个地址相同
return true;//肯定是同一个对象
if (obj == null)//传进来的不失控(调用方法对象肯定不是空的)
return false;//不是一个对象
//判断两个对象 是否是同一个类创建出来的对象
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
example:
编写一个程序,获取10个1至20的随机数,要求随机数不能重复
HashSet<Integer> set = new HashSet<>();
while (set.size() < 10) {
int random = (int)(Math.random()*(20 - 1 + 1) + 1);
set.add(random);
}
System.out.println(set);
for (Integer integer : set) {
System.out.println(integer);
}
去重系统类的对象的时候 不用重写equals方法和hashCode方法了
example:刷锅法:
利用set集合a , b , c , d
去除ArrayList集合中的重复元素(操作原ArrayList)
ArrayList保存了a,a,b,b,c,c,d,d
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("a");
list.add("b");
list.add("b");
list.add("c");
list.add("c");
list.add("d");
list.add("d");
HashSet<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c");
set.add("d");
set.addAll(list);
//清空list集合
list.clear();
//把所有元素放回list中
list.addAll(set);
System.out.println(list
2.linkedHashCode:
linked表示有序(怎么存的 打印出来还是那个顺序)
3.TreeSet:排序的功能
先了解一下二叉树:
存储规则:
比我小的数放到我的左边 (返回负数的情况)
比我大的数放到我的右边 (返回正数的情况)
返回的是0 就不存储
输出的规则 以升序打印
TreeSet在存储的时候
只跟compareTo的返回值有关
看一下效果:
TreeSet<Integer> set = new TreeSet<>();
set.add(10);
set.add(7);
set.add(15);
set.add(19);
set.add(19);
set.add(9);
System.out.println(set);
example:
在一个集合ArrayList中存储了无序并且重复的字符串
要求 排序,而且还不能去除重复(用比较器)
主要按字符串长度比较 次要按字符比
先创建比较器 在比较器中写排序规则:
//创建比较器
class StringLengthImpl implements Comparator<String>{
//实现比较器方法
@Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
int length = o1.length() - o2.length();
//主要按长度 次要按字符串
int num = o1.compareTo(o2);
int rel = length == 0 ? num : length;
return rel == 0 ? 1 : rel;
}
}
利用TreeSet的构造方法 直接将比较器的实现类传进去
ArrayList<String> list = new ArrayList<>();
list.add("asdns");
list.add("xsdns");
list.add("xsdns");
list.add("asdssans");
list.add("dns");
list.add("dns");
list.add("assdsdaasddns");
list.add("adasns");
//创建一个TreeSet
TreeSet<String> set = new TreeSet<>(new StringLengthImpl());
set.addAll(list);
list.clear();
list.addAll(set);
System.out.println(list);