Set接口和List接口一样,同样继承自Collection接口。Set接口中的元素无序,并且都会以某种规则保证存入的元素不出现重复。因此,我们可以利用Set集合的这个特性是实现一组数据的去重工作。
根据对象哈希值,确定元素在集合中的存储位置,因此存取和查找性能良好。
以二叉树的方式来存储元素,可以实现对集合中的元素进行排序。
hashCode()
方法来确定元素的存储位置,然后再调用元素对象的equals()
方法来确保该位置没有重复元素。package net.hw.lesson22;
import java.util.HashSet;
import java.util.Iterator;
/**
* 功能:创建与遍历专业哈希集合
* 作者:华卫
* 日期:2020年05月24日
*/
public class Example2201 {
public static void main(String[] args) {
// 创建专业哈希集合
HashSet<String> majors = new HashSet<>();
// 判断集合是否为空
System.out.println("majors.isEmpty() = " + majors.isEmpty());
// 添加元素(故意添加重复的元素)
majors.add("计算机应用技术专业");
majors.add("软件技术专业");
majors.add("大数据技术专业");
majors.add("软件技术专业");
majors.add("人工智能专业");
// 输出整个集合
System.out.println(majors);
// 遍历专业哈希集合
// 1. 采用增强for循环遍历集合
System.out.print("采用增强for循环遍历集合:");
for (String major : majors) {
System.out.print(major + " ");
}
System.out.println();
// 2. 采用Lambda表达式遍历集合
System.out.print("采用Lambda表达式遍历集合:");
majors.forEach(major -> System.out.print(major + " "));
System.out.println();
// 3. 采用迭代器遍历集合
System.out.print("采用迭代器遍历集合:");
Iterator<String> iterator = majors.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
// 查询元素
String major = "大数据技术专业";
boolean isFound = majors.contains(major);
if (isFound) {
System.out.println("专业集合里包含了[" + major + "]。");
} else {
System.out.println("专业集合里不包含[" + major + "]。");
}
// 哈希集合没有提供修改元素的方法
// 删除元素
major = "计算机应用技术专业";
boolean isDeleted = majors.remove(major);
if (isDeleted) {
System.out.println("[" + major + "]已从专业集合里删除。");
System.out.println("结果集合:" + majors);
} else {
System.out.println("专业集合里不包含[" + major + "]。");
}
// 清空集合元素
majors.clear();
System.out.println("清空集合元素之后的集合:" + majors);
}
}
indexOf()
方法,而只有contains()
方法来判断集合里是否包含了某个元素。hashCode()
和equals()
方法。在案例Example2201中,将String存入HashSet中,而String类已经默认重写了hashSet()与equals()方法,因此没有任何问题。
下面我们来演示将自定义的类型对象存入HashSet,看一看会出现什么样的结果。
package net.hw.lesson22;
/**
* 功能:学生类
* 作者:华卫
* 日期:2020年05月24日
*/
public class Student {
private String id;
private String name;
public Student(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}
package net.hw.lesson22;
import java.util.HashSet;
/**
* 功能:演示学生哈希集合
* 作者:华卫
* 日期:2020年05月24日
*/
public class Example2202 {
public static void main(String[] args) {
// 创建学生哈希集合
HashSet<Student> students = new HashSet<>();
// 创建学生对象
Student stu1 = new Student("201901", "李晓红");
Student stu2 = new Student("201902", "钟文艳");
Student stu3 = new Student("201903", "郑智化");
Student stu4 = new Student("201902", "钟文艳"); // 重复记录
// 将学生对象添加到集合
students.add(stu1);
students.add(stu2);
students.add(stu3);
students.add(stu4);
// 遍历输出学生哈希集合
students.forEach(student -> System.out.println(student));
}
}
如果我们认为id相同的学生就是同一个学生,那么我们来重写Student类的hashCode()与equals()方法。
package net.hw.lesson22;
/**
* 功能:学生类
* 作者:华卫
* 日期:2020年05月24日
*/
public class Student {
private String id;
private String name;
public Student(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
@Override
public int hashCode() {
return id.hashCode();
@Override
public boolean equals(Object o) {
// 判断是否是同一对象
if (this == o) {
return true;
}
// 判断对象是否是学生对象
if (o instanceof Student) {
// 将对象强制转换为学生对象
Student student = (Student) o;
return id.equals(student.id);
}
return false;
}
}
如果将Student类equals()方法里的代码改成return id.equals(student.id) && name.equals(student.name);
,那么会出现什么情况呢?
同一层的元素可分为1个根节点元素和2个子节点元素,左边的元素总是小于右边的元素。
方法声明 | 功能描述 |
---|---|
Object first() | 返回TreeSet集合的首个元素 |
Object last() | 返回TreeSet集合的最后一个元素 |
Object lower(Object o) | 返回TreeSet集合中小于给定元素的最大元素,如果没有返回null |
Object floor(Object o) | 返回TreeSet集合中小于或等于给定元素的最大元素,如果没有返回null |
Object higher(Object o) | 返回TreeSet集合中大于给定元素的最小元素,如果没有返回null |
Object ceiling(Object o) | 返回TreeSet集合中大于或等于给定元素的最小元素,如果没有返回null |
Object pollFirst() | 移除并返回集合的第一个元素 |
Object pollLast() | 移除并返回集合的最后一个元素 |
package net.hw.lesson22;
import java.util.Iterator;
import java.util.TreeSet;
/**
* 功能:创建与操作TreeSet对象
* 作者:华卫
* 日期:2020年05月24日
*/
public class Example2203 {
public static void main(String[] args) {
// 创建TreeSet对象
TreeSet<Integer> nums = new TreeSet<>();
// 添加元素
nums.add(5);
nums.add(13);
nums.add(8);
nums.add(17);
nums.add(11);
nums.add(25);
nums.add(15);
nums.add(5); // 重复
// 输出整个集合
System.out.println("整个集合:" + nums);
// 遍历集合元素
// 1. 采用增强for循环遍历集合
System.out.print("采用增强for循环遍历集合:");
for (Integer num : nums) {
System.out.print(num + " ");
}
System.out.println();
// 2. 采用Lambda表达式遍历集合
System.out.print("采用Lambda表达式遍历集合:");
nums.forEach(num -> System.out.print(num + " "));
System.out.println();
// 3. 采用迭代器遍历集合
System.out.print("采用迭代器遍历集合:");
Iterator<Integer> iterator = nums.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
// 获取首尾元素
System.out.println("集合首元素:" + nums.first());
System.out.println("集合尾元素:" + nums.last());
// 比较获取元素
System.out.println("大于或等于14的最小元素:nums.higher(14) = " + nums.higher(14));
System.out.println("大于或等于14的最小元素:nums.ceiling(14) = " + nums.ceiling(14));
System.out.println("小于或等于14的最大元素:nums.lower(14) = " + nums.lower(14));
System.out.println("小于或等于14的最大元素:nums.floor(14) = " + nums.floor(14));
System.out.println("大于或等于26的最小元素:nums.higher(26) = " + nums.higher(26));
System.out.println("大于或等于26的最小元素:nums.ceiling(26) = " + nums.ceiling(26));
System.out.println("小于或等于4的最大元素:nums.lower(4) = " + nums.lower(4));
System.out.println("小于或等于4的最大元素:nums.floor(4) = " + nums.floor(4));
// 查询元素
Integer num = 11;
boolean isFound = nums.contains(num);
if (isFound) {
System.out.println("元素[" + num + "]在集合里。");
} else {
System.out.println("元素[" + num + "]不在集合里。");
}
// 删除首元素
Integer first = nums.pollFirst();
System.out.println("删除首元素[" + first + "]后的集合:" + nums);
// 删除尾元素
Integer last = nums.pollLast();
System.out.println("删除尾元素[" + last + "]后的元素:" + nums);
// 按元素删除
num = 11;
boolean isDeleted = nums.remove(num);
if (isDeleted) {
System.out.println("元素[" + num + "]已从集合里删除。");
System.out.println("结果集合:" + nums);
} else {
System.out.println("元素[" + num + "]不在集合里。");
}
}
}
要求存储的元素类必须实现Comparable接口,并重写compareTo()方法。
package net.hw.lesson22;
/**
* 功能:动物类
* 实现Comparable接口
* 作者:华卫
* 日期:2020年05月24日
*/
public class Animal implements Comparable<Animal> {
private String name;
private int age;
public Animal(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 int compareTo(Animal o) {
if (this.age == o.age) { // 年龄相同比较姓名
return this.name.compareTo(o.name); // 升序,若要降序,则 o.name.compareTo(this.name);
} else {
return this.age - o.age; // 升序,若要降序,则 o.age - this.age
}
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package net.hw.lesson22;
import java.util.TreeSet;
/**
* 功能:实现动物类集合排序
* 作者:华卫
* 日期:2020年05月24日
*/
public class Example2204 {
public static void main(String[] args) {
// 创建动物集合
TreeSet<Animal> animals = new TreeSet<>();
// 创建动物对象
Animal animal1 = new Animal("欢欢", 4);
Animal animal2 = new Animal("瑞瑞", 7);
Animal animal3 = new Animal("灵灵", 3);
Animal animal4 = new Animal("豆豆", 5);
Animal animal5 = new Animal("乐乐", 3);
// 将动物对象添加到集合
animals.add(animal1);
animals.add(animal2);
animals.add(animal3);
animals.add(animal4);
animals.add(animal5);
// 遍历动物集合
animals.forEach(animal -> System.out.println(animal));
}
}
要求自定义一个比较器,该比较器必须实现Comparator接口,并重写compare()方法,然后将该比较器作为参数传入集合的有参构造。
package net.hw.lesson22;
import java.util.Comparator;
import java.util.TreeSet;
/**
* 功能:创建字符串集合,按照字符串长度排序
* 作者:华卫
* 日期:2020年05月24日
*/
public class Example2205 {
public static void main(String[] args) {
// 1. 创建字符串集合,传入Comparator接口匿名对象
TreeSet<String> names = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length(); // 按字符串长度升序排列
}
});
// 添加字符串元素
names.add("Black");
names.add("Amy");
names.add("Amanda");
names.add("Anne");
// 输出整个集合
System.out.println("姓名集合(按长度升序):" + names);
// 2. 创建字符串集合,使用Lambda表达式定制排序规则
TreeSet<String> words = new TreeSet<>((o1, o2) -> o2.length() - o1.length());
// 添加字符串元素
words.add("天长地久");
words.add("爱");
words.add("勿忘我");
words.add("光明");
// 输出整个集合
System.out.println("词语集合(按长度降序):" + words);
}
}
去掉重复IP地址,统计不同IP地址的个数。
192.168.234.21
192.168.234.22
192.168.234.21
192.168.234.21
192.168.234.23
192.168.234.21
192.168.234.21
192.168.234.21
192.168.234.25
192.168.234.21
192.168.234.21
192.168.234.26
192.168.234.21
192.168.234.27
192.168.234.21
192.168.234.27
192.168.234.21
192.168.234.29
192.168.234.21
192.168.234.26
192.168.234.21
192.168.234.25
192.168.234.25
192.168.234.21
192.168.234.22
192.168.234.21