Set集合
List集合的特点:元素有序(存取顺序一致),元素可以重复
Set集合特点:元素无序(素存取顺序不一致),元素不可以重复
常用子类:HashSet,TreeSet,LinkedHashSet
1.(哈希表数据类型)
HashSet<String> set = new HashSet<>()
set.add("aaaa");
set.add("bbbb");
set.add("wusong");
set.add("cccc");
set.add("bbbb");
set.add("wusong");
set.add("cccc");
遍历集合
for(String s:set){
sout(s);
}
public class Test01 {
public static void main(String[] args) {
HashSet<Integer> hashSet = new HashSet<>();
hashSet.add(10);
hashSet.add(20);
hashSet.add(30);
hashSet.add(20);
hashSet.add(40);
hashSet.add(50);
hashSet.add(10);
hashSet.add(30);
hashSet.add(20);
hashSet.add(30);
System.out.println(hashSet.size());
for (Integer i: hashSet) {
System.out.println(i);
}
}
}
Integer类型
//输出:
// 5
// 50
// 20
// 40
// 10
// 30
存入的元素无序且唯一
自定义一个Student对象
SetDemo3
new Student("qqq");
new Student("www");
new Student("eee");
new Student("rrr");
new Student("ttt");
new Student("eee");
new Student("rrr");
new Student("ttt");
new Student("ttt");
new Student("eee");
HashSet<Student> student = new HashSet<Student> ;
student.add(s1);
.
.
.
===============>重写hashcode和equals方法试试=================
提问:Student.size()值为什么为10 ???
解释:
add 方法在存储的时候,会调用HashCode()方法和Equals()方法
那么在往Set集合中存对象的时候,默认比较地址值,如果地址不同,就存进去
通常我们认为如果两个对象的成员变量的值一样,那么两个对象一样,因此
我们要重写方法.
--------->HashSet集合保证元素的唯一性是靠元素重写HashCode()方法和equals()方法
String类型和Integer类型已经默认重写了hashcode()方法和equals()方法
HashSet的特点:
1. 底层数据结构数据结构哈希表,线程不安全,效率高,允许存储null元素,元素无序且唯一,
哈希表:具有数组和链表的特点
HashSet允许存储null;
integer.add(null);
//HashSet(collecton<? extends E> c)
arrayList<Integer> integer1 = new ArrayList<>();
integer1.add(10);
.
.
.
HashSet<Integer> integer2 = new HashSet<>(integer1);
通过有参构造去除list集合中重复元素
LinkedHashSet
有序且唯一
LinkedHashSet也是Set集合子类(可预知迭代顺序的Set接口的哈希表和...)
LinkedHashSet 底层数据结构是链表和哈希表
链表保证元素有序,哈希表保证了元素唯一,不同步,线程不安全,效率高
TreeSet
底层数据结构是二叉树
TreeSet<Integer> treeSet = new TreeSet<Integer>();
treeSet.add(10);
.
.
.
foreach遍历
元素唯一(重复元素去除),且能排序
二叉树的结构:
20,18,23,22,17,24,19,18,24
第一次存储以第一个作为树根
第二次存,和树根比较,比树根小左边,大放右边
第三次存,和树根比较,小则放左,大则放右
取出规则:=======回想三种遍历方式
对元素进行排序有两种方式,具体使用那种排序方式,根据构造方法决定
如果是空参构造,用的是自然排序.
如果是有参构造,用的是比较器排序
自然排序,对元素有要求:
要求元素必须实现一个Compareble接口,并且要重写compareTo()方法根据此方法的返回值
正负来决定元素的排列顺序.零决定元素唯一性.
同样Integer类型和String类型已经重写了,但是自定义对象要自己重写
如在我的Student类中
public class Student implements Comparable<Student>{
@Override
public int compareTo(Student s) {
//按年龄排序
//return (this.getAge()-s.getAge());
int r = this.getAge()-s.getAge();
int r2 = r == 0?this.getname.compareTo(s.getname):r
return r2;
--------------------------------------------------------
//按名字长度排序
//int r = this.getName().length-s.getName().length;
//int r2= r == 0?this.getAge().compareTo(s.getAge()):r;
//return r2;
//按姓名长度来排
--------------------------------------------------------
int r =this.name.length()-s.name.length();
int r2 = r==0?this.age-s.age:r;
int r3 = r2 ==0?this.name.compareTo(s.name):r2;
return r3;
}
}
在此时是比较的年龄,但是年龄一样并不能说明是同一个对象还需要比较姓名
需要改进:this.getname.compareTo(s.getname);
比较器排序:
创建实类
public class MyCompareTor implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
//根据条件来排序
int r = s1.getName().length() - s2.getName().length();
int r2 = r == 0 ? s1.getAge() - s2.getAge() : r;
int r3 = r2 == 0 ? s1.getName().compareTo(s2.getName()) : r2;
return r3;
}
}
public class TreeSetDemo2 {
public static void main(String[] args) {
//比较器排序
MyCompareTor myCompareTor = new MyCompareTor();
Student s1 = new Student("刘亦菲", 30);
Student s2 = new Student("尼古拉斯赵四", 30);
Student s3 = new Student("杰森斯坦斯达", 30);
Student s4 = new Student("马特呆萌", 37);
Student s5 = new Student("贝加尔朵", 37);
Student s6 = new Student("汤姆克鲁斯", 35);
Student s7 = new Student("汤姆汉克斯", 30);
Student s8 = new Student("马特呆萌", 37);
Student s9 = new Student("马特呆萌", 37);
TreeSet<Student> students = new TreeSet<>(myCompareTor);
students.add(s1);
students.add(s2);
students.add(s3);
students.add(s4);
students.add(s5);
students.add(s6);
students.add(s7);
students.add(s8);
students.add(s9);
for(Student student:students){
System.out.println(student.getName()+"====="+student.getAge());
}
}
}
比较器用匿名内部类实现
public class TreeSetDemo3 {
public static void main(String[] args) {
//通过匿名内部类来传一个比较器
Student s1 = new Student("刘亦菲", 30);
Student s2 = new Student("尼古拉斯赵四", 30);
Student s3 = new Student("杰森斯坦斯达", 36);
Student s4 = new Student("马特呆萌", 36);
Student s5 = new Student("贝加尔朵", 37);
Student s6 = new Student("汤姆克鲁斯", 35);
Student s7 = new Student("汤姆汉克斯", 30);
Student s8 = new Student("马特呆萌", 32);
Student s9 = new Student("马特呆萌", 33);
TreeSet<Student> students = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int r = s1.getAge() - s2.getAge();
int r2 = r == 0 ? s1.getName().compareTo(s2.getName()) : r;
return -r2;
}
});
students.add(s1);
students.add(s2);
students.add(s3);
students.add(s4);
students.add(s5);
students.add(s6);
students.add(s7);
students.add(s8);
students.add(s9);
for (Student student : students) {
System.out.println(student.getName() + "=====" + student.getAge());
}
System.out.println("------------------------------");
Integer[] arr=new Integer[]{3, 5, 9, 9, 2};
Arrays.sort(arr, new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return -(a-b);
}
});
System.out.println(Arrays.toString(arr));
}
}
Comparetor比较器,是一个接口,接口中有一个比较的方法
一丶编写一个程序,获取10个到1到20的随机数,不要重复
1.生成随机数,Random
2.去重
Random random = new Random();
//int num = random.nextInt(20);
//创建一个集合
TreeSet<Integer> integer = new TreeSet<>();
while(integer.size()<10){
int num = random.nextInt(20)+1;
}
sout(integer);