Set集合
不包含重复元素;没有带索引的方法,所以不能使用普通for循环遍历
set是一个接口不能直接实例化,得找它的实现类
set集合存储字符串并遍历
HashSet:对集合的迭代顺序不做任何保证
Set<String> set = new HashSet<String>();//创建集合对象
//添加元素
set.add("Hello");
set.add("World");
set.add("java");
//添加元素 不包含重复元素的集合
set.add("World");
//遍历 增强for循环
for(String s : set){
sout(s);
}
输出顺序不一样,就是因为HashSet不能保证迭代顺序
哈希值
是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类种有一个方法可以获取对象的哈希值
Student s1 = new Student(name:"林青霞",age:30);//创建一个学生对象
//通过对象调用hashCode方法得到哈希值
sout(s1.hashCode());
sout(s1.hashCode());
Student s2 = new Student(name:"林青霞",age:30);//创建一个学生对象
sout(s2.hashCode());
同一个对象多次调用hashCode()方法返回的哈希值是相同的
即便成员变量是相同的,但是因为对象不同所以默认情况下哈希值也是不同的,因为如果重写hashCode方法,返回默认值变成一样的,那输出的就是一样的了
通过方法重写,可以实现不同对象的哈希值是相同的
不同对象的哈希值不同,相同对象的哈希值相同
这两个对象的哈希值相同是因为字符串重写了object的hashCode方法
HashSet集合概述和特点
在util包下
HashSet<String> hs = new HashSet<String>();//创建集合对象
//添加元素,没有索引
hs.add("Hello");
hs.add("World");
hs.add("java");
//遍历 增强for循环
for(String s : hs){
sout(s);
}
HashSet集合保证元素唯一性源码分析
常见数据结构之哈希表
HashSet集合无参构造方法默认集合初始长度是16,然后对数据的哈希值对16取余,余数是多少就存放在哪个位置,首先hello先存放在2位置,然后发现world也需要存放在2位置,然后两者的哈希值不一样,所以形成链表,然后java要和2位置的两个元素分别比较哈希值发现不同,形成链表;后面那个world也是2位置,需要和前面三个进行比较,发现和第一个哈希值不同,然后和第二个比发现和前面的world哈希值相同,然后及比较内容,发现内容也相同,从而判定为先相同元素,不进行存储
通话元素存放在3位置,然后对重地元素进行分析,发现也需要放在3位置,3位置有元素,所以需要和通话元素进行哈希值比较,发现哈希值相同,当哈希值相同时就需要对内容荣进行比较,然后对他们的内容进行对比,发现内容不相同,所以重地元素也可以存储进来形成链表
案例 HashSet集合存储学生并遍历
HashSet<Student> hs = new HashSet<Student>();//创建HashSet集合对象
Student s1 = new Student(name:"林青霞",age:30);//创建一个学生对象
Student s2 = new Student(name:"张曼玉",age:35);//创建一个学生对象
Student s3 = new Student(name:"王祖贤",age:33);//创建一个学生对象
//s3和s4成员变量值相同,按照要求就认为是同一个对象,所以s4就应该存储不进去
Student s4 = new Student(name:"王祖贤",age:33);//创建一个学生对象
//把学生添加到集合
hs.add(s1);
hs.add(s2);
hs.add(s3);
hs.add(s4);
//遍历 增强for循环
for(Student s : hs){
sout(s.getName() + "," + s.getAge());
但是按照上面的的代码s4是添加成功的了,所以需要进行修改才能保证元素的唯一性
所以Student类需要重写HashCode方法和equals方法,然后就保证唯一性了
LinkedHashSet集合概述和特点
是由哈希表和链表实现的Set接口,具有可预测的迭代顺序
由链表保证元素有序,也就是说元素的存储和去除顺序是一致的
LinkedHashSet 存储字符串并遍历
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();//创建集合对象
//添加元素
linkedHashSet.add("Hello");
linkedHashSet.add("World");
linkedHashSet.add("java");
//添加元素 不包含重复元素的集合
linkedHashSet.add("World");
//遍历 增强for循环
for(String s : linkedHashSet){
sout(s);
}
TreeSet集合概述和特点
间接的实现了Set接口
TreeSet 存储整数并遍历
集合里存储的是引用类型,所以存储整数应该用她的包装类Interger
TreeSet<Interger> ts = new TreeSet<Interger>();//创建集合对象
//添加元素 自动装箱
ts.add(10);
ts.add(40);
ts.add(30);
ts.add(50);
ts.add(20);
//添加元素 不包含重复元素的集合
ts.add(30);
//调用的是无参构造 所以是自然排序,是从小到大
//遍历 增强for循环
for(Interger i : ts){
sout(i);
}
自然排序Comparable的使用
TreeSet<Student> ts = new TreeSet<Student>();//创建HashSet集合对象
Student s1 = new Student(name:"xishi",age:29);//创建一个学生对象
Student s2 = new Student(name:"wangzhaojun",age:28);//创建一个学生对象
Student s3 = new Student(name:"diaochan",age:30);//创建一个学生对象
Student s4 = new Student(name:"yangyuhuan",age:33);//创建一个学生对象
//s4和s5成员年龄相同
Student s5 = new Student(name:"linqingxia",age:33);//创建一个学生对象
//把学生添加到集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
//遍历 增强for循环
for(Student s : ts){
sout(s.getName() + "," + s.getAge());
出现异常
是因为如果要做自然排序就得让类实现该接口,因为该接口可以对类的对象进行排序,所以需要让学生类实现Comparable这个接口,然后重写这个接口里面的方法compareTo
因为重写的compareTo方法返回的是0,所以在添加第二个 第三个 第四个元素的时候就会认为和第一个是同一个元素,所以添加不上,返回值是0,说明元素是相等的,重复的就不会存储。
改成return 1;说明s2比s1大,s3比s2大,s4比s3大,就可以添加,然后按照从小到大的顺序输出,也就是正序
改成return -1;说明s2比s1小,s3比s2小,s4比s3小,就可以添加,然后按照从小到大的顺序输出,也就是倒序
返回是0,就认为是重复的相等的不添加;返回是负数,就认为是后面的小,也就是倒叙存储;返回是正数,就认为是后面的大,也就是升序存储
题目要求按照年龄从小到大排序,按照姓名的字母顺序排序
也就是说要改进重写的compareTo方法的返回值
方法内部其实本身就有这个属性,拿s1 s2举例来看,s1不需要和别人比,s2需要和s1比,这个this就是s2,这个s就是s1
用后面的age减去前面的,返回差值,就是升序,也就就是从小到大;用前面的age减去后面的,返回差值,就是降序,也就是从大到小
当年龄一样的时候返回0,就存储不进来,但是按照题目要求要用名字首字母排序,所以进行更改
字符串本身可以自行排序
TreeSet<Student> ts = new TreeSet<Student>();//创建HashSet集合对象
Student s1 = new Student(name:"xishi",age:29);//创建一个学生对象
Student s2 = new Student(name:"wangzhaojun",age:28);//创建一个学生对象
Student s3 = new Student(name:"diaochan",age:30);//创建一个学生对象
Student s4 = new Student(name:"yangyuhuan",age:33);//创建一个学生对象
//s4和s5成员年龄相同
Student s5 = new Student(name:"linqingxia",age:33);//创建一个学生对象
//s6和s5成员姓名年龄都相同
Student s6 = new Student(name:"linqingxia",age:33);//创建一个学生对象
//把学生添加到集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
//遍历 增强for循环
for(Student s : ts){
sout(s.getName() + "," + s.getAge());
int num = this.age - s.age;
int num1 = num == 0?this.name.compareTo(s.name):num
//当年龄相同的时候就返回this.name.compareTo(s.name),当年龄不同的时候就返回num
renturn num1;
自然排序Comparator的使用
带参构造,也就是指定比较器的方式,按照年龄从小到大排序
传递了一个比较器接口
//创建HashSet集合对象匿名内部类方式 下面会自动重写conpare方法
TreeSet<Student> ts = new TreeSet<Student>(**new Comparator<Student>({
@Override
public int compare(Student s1,Student s2){
//这个方法内部的this代表的是TreeSet而不是学生,所以方法的参数传了两个学生对象
//年龄从小到大排序
//this.age - s.age
//**s1是this s2是s**
int num = s1.getAge()-s2.getAge();//在这里不能访问学生类的私有成员
int num1 = num == 0?s1.getName().compareTo(s2.getName()):num
return num1;
}
}**);
Student s1 = new Student(name:"xishi",age:29);//创建一个学生对象
Student s2 = new Student(name:"wangzhaojun",age:28);//创建一个学生对象
Student s3 = new Student(name:"diaochan",age:30);//创建一个学生对象
Student s4 = new Student(name:"yangyuhuan",age:33);//创建一个学生对象
//s4和s5成员年龄相同
Student s5 = new Student(name:"linqingxia",age:33);//创建一个学生对象
//s6和s5成员姓名年龄都相同
Student s6 = new Student(name:"linqingxia",age:33);//创建一个学生对象
//把学生添加到集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
//遍历 增强for循环
for(Student s : ts){
sout(s.getName() + "," + s.getAge());
Set案例 成绩排序
通过比较器进行排序实现
s1出现在前面是从低到高,s2出现在前面是从高到低
总分相同按照语文成绩升序进行
当总分和单科分数都一样时,按照名字从小到大排序
@Override
public int compare(Student s1, Student s2) {
// 升序
return s1.getAge()-s2.getAge();
return s1.getAge().compareTo(s2.getAge());
// 降序
return s2.getAge()-s1.getAge();
return s2.getAge().compareTo(s1.getAge());
参考网址 comparable和comparator的区别
http://www.manongjc.com/artic...
Comparator和Comparable的区别
Comparable:自己(this)和别人(参数)比较,自己需要实现Comparable接口,重写比较的规则compareTo方法
Comparator:相当于找一个第三方的裁判,比较两个
Comparator的排序规则:
o1-o2:升序
Comparable接口的排序规则:
被排序的集合里边存储的元素,必须实现Comparable,重写接口中的方法compareTo定义排序的规则
public class Person implements Comparable<Person>{
自己(this)-参数:升序
Set案例 不重复的随机数
//创建HashSet集合对象
Set<Integer> set = new HashSet<Integer>();
//创建随机数对象
Random r = new Random();
//判断集合的长度是不是小于10
while(set.size()<10){
//产生一个随机数添加到集合1-20之间
int number = r.nextInt(bound:20)+1;
set.add(number);//有重复的无法添加进去
//遍历 增强for循环
for(Integer i : set){
sout(i);
}
改成TreeSet集合
//创建TreeSet集合对象
Set<Integer> set = new TreeSet<Integer>();
会进行从小到大的排序
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。