一、Set接口
对应数据结构中的哈希表:无序、不重复的非线性结构
set原码:
不能包含重复元素的的集合,通常情况,set包含单独的值(map是键值对)
二、.Set接口实现子类
1. HashSet
1). 常见方法:
add()、contains()
@Test
void testSet01() {
// HashSet 是java中的一个标准的哈希表
Collection<Integer> nums = new HashSet<>();
nums.add(123);
nums.add(456);
nums.add(789);
nums.add(1);
nums.add(13);
nums.add(258);
nums.add(10);
System.out.println(nums);
}
和自己添加的值顺序不同,无序
无序不是随机,会用特定的hash算法算值,而不是随机
@Test
void testSet01() {
// HashSet 是java中的一个标准的哈希表
Collection<Integer> nums = new HashSet<>();
nums.add(123);
nums.add(456);
nums.add(789);
nums.add(1);
nums.add(13);
nums.add(258);
nums.add(10);
// add方法会返回一个boolean,表示是否添加成功
System.out.println(nums.add(31));
// 添加失败,返回false,表示之前已经存在了这个值
System.out.println(nums.add(31));
//是否包含某个元素
System.out.println(nums.contains(1));
System.out.println(nums.contains(11));
System.out.println(nums);
}
2). 哈希表遍历
注意:哈希表是无序的(没有下标),因此无法使用常规的循环,通过下标访问
(1)迭代器访问
@Test
void testSet02() {
// HashSet 是java中的一个标准的哈希表
Collection<Integer> nums = new HashSet<>();
nums.add(123);
nums.add(456);
nums.add(789);
nums.add(1);
nums.add(13);
nums.add(258);
nums.add(10);
//迭代器访问
Iterator<Integer> it = nums.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
(2)for循环加强进行遍历
for (Integer i : nums) {
System.out.println(i);
}
(3)forEach进行遍历
nums.forEach((i) ->System.out.println(i));
2. TreeSet:
这个set是使用二叉树(红黑树)实现的一个集合,因此该集合是有序的
1). 排序规律
(1). 字符串按accll码值排序
@Test
void testSet03() {
Set<String> ss = new TreeSet<>();
// 有序的集合
ss.add("apply");
ss.add("huawei");
ss.add("mi");
ss.add("mm");
ss.add("vivo");
ss.add("OPPO");
System.out.println(ss);
}
(2). 数字按大小排序
@Test
void testSet04() {
Set<Integer> ss = new TreeSet<>();
// 有序的集合
ss.add(1);
ss.add(2);
ss.add(33);
ss.add(333);
ss.add(12);
ss.add(102);
ss.add(50);
System.out.println(ss);
}
(3).对象
先定义一个Person类
package com.openlab.day20.entity;
public class Person {
private int id;
private String name;
private String nickname;
private String gender;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person() {
}
public Person(int id, String name, String nickname, String gender, int age) {
super();
this.id = id;
this.name = name;
this.nickname = nickname;
this.gender = gender;
this.age = age;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", nickname=" + nickname + ", gender=" + gender + ", age=" + age
+ "]";
}
}
@Test
void testSet06() {
Set<Person> ss = new TreeSet<>();
ss.add(new Person(1, "cc", "曹孟德", "男", 32));
ss.add(new Person(2, "lb", "刘玄德", "男", 28));
ss.add(new Person(3, "sq", "孙百万", "男", 18));
ss.add(new Person(4, "zf", "张翼德", "男", 24));
ss.add(new Person(5, "gy", "关云长", "男", 26));
ss.add(new Person(6, "hhd", "夏侯惇", "男", 43));
ss.add(new Person(7, "lb", "吕奉先", "男", 23));
ss.add(new Person(8, "dc", "貂蝉", "男", 16));
System.out.println(ss);
}
jvm不知道Person类应该怎样排序
String和Integer在定义的时候已经指定了排序规则,而我们自己写的Person没有制定规则,是让jvm自动去完成,但是jvm也不知道
注意:在java中,如果对象需要比较,则必须让该类实现Comparable接口
String和Integer(包装类)都实现了此接口
所以Person要想进行比较也需要实现Comparable接口
要求传递一个跟原对象进行比较
Comparable接口有个泛型,要求传递过来一个东西跟原对象进行比较,我们传递Person,比较比较同一个对象,不是同一个对象比较没有意义
重写方法:
该方法返回一个int的值
若返回一个 >0 的数,按照正序排序
若返回一个 <0 的数,按照降序排序
若返回一个 =0 的数,不变
@Override
public int compareTo(Person o) {
return 0;}
package com.openlab.day20.entity;
public class Person implements Comparable<Person> {
private int id;
private String name;
private String nickname;
private String gender;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person() {
}
public Person(int id, String name, String nickname, String gender, int age) {
super();
this.id = id;
this.name = name;
this.nickname = nickname;
this.gender = gender;
this.age = age;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", nickname=" + nickname + ", gender=" + gender + ", age=" + age
+ "]";
}
@Override
public int compareTo(Person o) {
// 指定需要排序的规则!!!
// 指定规则:id的升序排列
// return this.getId() - o.getId();
// 指定规则:age的降序排列
return o.getAge() - this.getAge();
}
}
return this.getId() - o.getId();
比较当前对象和下一个对象的id,如果大于零,相当于return 1,
代码相当于
int temp = this.getId() - o.getId();
if(temp > 0){
return 1;
}else{
return -1;
}
2). 去重
且TreeSet是有序的
HashSet就不是了
@Test
void testSet05() {
// 生成一个大小固定的list
List<Integer> list = Arrays.asList(1,3,34,5,5,6,7,88,8,8,88,99);
Set<Integer> ss = new TreeSet<>();
Set<Integer> s = new HashSet<>();
ss.addAll(list);
System.out.println(ss);
s.addAll(list);
System.out.println(s);
}
Arrays.asList() 将不定长的数据以ArrayList的形式返回,返回的是一个固定大小的ArrayList(传了几个数据就是几个,不能再改变)