一篇文章让你精通:java集合讲解(三,Set)
Posted 韶光不负
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一篇文章让你精通:java集合讲解(三,Set)相关的知识,希望对你有一定的参考价值。
一篇文章让你精通:java集合讲解(二,ArrayList)
上面二个链接,让大家对集合中的List有了一定的了解,如果大家回想要继续加强理解,建议大家打开jdk8下的List源码继续解析一下。废话不多说下面让我们来看看Set的内容吧!
目录
解决问题一:在Student类下重写equals与 hashCode方法(缺一不可)。
解决问题2:在Student在threeSet下重写compareTo的比较方法(按照姓名比较),这样使用treeHash就不会报错了。
报错显示:java.lang.ClassCastException: com.itheima.类名称 cannot be cast to java.lang.Comparable
Set
特点:无序,唯一(数据不重复)
HashSet
特点:采用HashSet哈希表存储结构。
优点:添加速度快,查询速度快,删除速度快。
缺点:无序
add() | 末尾添加元素, 数组能自动装箱:就是数组封装。普通数据类型——>包装类 可以使用一个参数或者二个,一个时,添加元素,二个时,第一个参数:索引,第二个,添加元素 |
addAll(对象) addAll(下标,对象) | 复制添加对象全部元素,默认在后面添加 当有二个参数后,表示在下标后添加对象全部元素。 |
remove() | 当输入的是对象时,删除对象,当输入的是对下标,删除下标, |
el1.removeAll(el2) | 在el1中删除el2中相同的元素。 |
list.retainAll(list2); | 在list中查找与list2相同的元素 |
clear() | 清空数组 |
contains(value) | 判断是否存在value值,返回布尔值 |
isEmpty() | 判断数组是否为空。 |
size() | 查看数组中真实存储的元素个数。与数组的length()方法返回不同 |
toString() | 遍历数组 |
import java.util.HashSet;
import java.util.Set;
public class Test {
public static void main(String[] args) {
//创建Set集合数组
Set<String> set= new HashSet();
//添加元素
set.add("javaSE");
set.add("javaEE");
set.add("english");
set.add("中文");
//可以添加相同的数据,但不会添加到集合中
set.add("javaSE");
//查看数量
System.out.println(set.size());
//遍历元素
System.out.println(set);
for (String ss:set) {
System.out.println(ss);
}
//数据清空
set.clear();
}
}
linkedHashSet
HashSet的子类,采用哈希表存储结构,同时使用了链表维护次序,有序(添加顺序)
import java.util.LinkedHashSet;
import java.util.Set;
public class Test {
public static void main(String[] args) {
//创建Set集合数组,有序,但是是存储的先后顺序
Set<String> set= new LinkedHashSet();
//添加元素
set.add("javaSE");
set.add("javaEE");
set.add("english");
set.add("中文");
//可以添加相同的数据,但不会添加到集合中
set.add("javaSE");
//查看数量
System.out.println(set.size());
//遍历元素
System.out.println(set);
for (String ss:set) {
System.out.println(ss);
}
//数据清空
set.clear();
}
}
TreeSet
特点:采用二叉树(红黑树,左子数小于根,右子树大于根,左右平衡)的存储结构
优点:有序,查询速度比List快(按照内容进行查找)
缺点:查询速度比HashSet快
add() | 末尾添加元素, 数组能自动装箱:就是数组封装。普通数据类型——>包装类 可以使用一个参数或者二个,一个时,添加元素,二个时,第一个参数:索引,第二个,添加元素 |
addAll(对象) addAll(下标,对象) | 复制添加对象全部元素,默认在后面添加 当有二个参数后,表示在下标后添加对象全部元素。 |
remove() | 当输入的是对象时,删除对象,当输入的是对下标,删除下标, |
el1.removeAll(el2) | 在el1中删除el2中相同的元素。 |
list.retainAll(list2); | 在list中查找与list2相同的元素 |
clear() | 清空数组 |
contains(value) | 判断是否存在value值,返回布尔值 |
isEmpty() | 判断数组是否为空。 |
size() | 查看数组中真实存储的元素个数。与数组的length()方法返回不同 |
toString() | 遍历数组 |
import java.util.Set;
import java.util.TreeSet;
public class Test {
public static void main(String[] args) {
//创建Set集合数组,有序,但是是存储的先后顺序
Set<String> set= new TreeSet();
//添加元素
set.add("javaSE");
set.add("javaEE");
set.add("english");
set.add("中文");
//可以添加相同的数据,但不会添加到集合中
set.add("javaSE");
//查看数量
System.out.println(set.size());
//遍历元素
System.out.println(set);
for (String ss:set) {
System.out.println(ss);
}
//数据清空
set.clear();
}
}
set的遍历方法(三种方法,无序:不能使用for循环)
//遍历元素 for-each
System.out.println(set);
for (String ss:set) {
System.out.println(ss);
}
//遍历元素 迭代器
Iterator<String> it=set.iterator();
while (it.hasNext()){
String elem =it.next();
System.out.println(elem);
}
//遍历元素 lambda表达式
set.forEach((elem)-> System.out.println(elem+" "));
练习:set存储自定义类的对象与操作(存储学生信息)
一,先定义一个学生的ApI.
(IDEA工具快速生成快捷键:Alt+insert)
import java.util.Objects;
//一个完整的API
public class Student implements Comparable<Student> {
//姓名
private String name;
//性别
private String sex;
//年龄
private int age;
//分数
private double score;
//重写TreeSet的比较规则
@Override
public int compareTo(Student other){
return this.name.compareTo(other.name);
}
public Student() {
//无参构造
}
public Student(String name, String sex, int age, double soore) {
//有参构造
this.name = name;
this.sex = sex;
this.age = age;
this.score = score;
}
//生成get方法
public String getName() {
return name;
}
public String getSex() {
return sex;
}
public int getAge() {
return age;
}
public double getScore() {
return score;
}
//生成set方法
public void setName(String name) {
this.name = name;
}
public void setSex(String sex) {
this.sex = sex;
}
public void setAge(int age) {
this.age = age;
}
public void setScore(double score) {
this.score = score;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Double.compare(student.score, score) == 0 &&
Objects.equals(name, student.name) &&
Objects.equals(sex, student.sex);
}
@Override
public int hashCode() {
return Objects.hash(name, sex, age, score);
}
//生成toString方法
@Override
public String toString() {
return "Student{" +
"name='" + name + '\\'' +
", sex='" + sex + '\\'' +
", age=" + age +
", score=" + score +
'}';
}
}
二,进行学生添加到set中
import java.util.HashSet;
import java.util.Set;
public class Test {
public static void main(String[] args) {
//创建Set集合数组,存储学生信息。
Set<Student> set= new HashSet();
//使用set存储多个学生信息
Student stu1= new Student("张三","男",18,60);
Student stu2= new Student("李四","男",28,75);
Student stu3= new Student("小明","男",20,90);
Student stu4= new Student("小美","女",18,100);
Student stu5= new Student("Jack","女",18,100);
//插入数据重复的信息看看现象
Student stu6= new Student("Jack","女",18,100);
//添加到Set中
set.add(stu1);
set.add(stu2);
set.add(stu3);
set.add(stu4);
set.add(stu5);
set.add(stu6);
//查看数量
System.out.println(set.size());
//遍历元素 for-each
System.out.println(set);
for (Student student1:set) {
System.out.println(student1);
}
//遍历元素 迭代器
// Iterator<Student> it=set.iterator();
// while (it.hasNext()){
// Student elem =it.next();
// System.out.println(elem);
// }
//遍历元素 lambda表达式
// set.forEach((elem)-> System.out.println(elem+" "));
//数据清空
// set.clear();
}
}
问题发现
1,HashSet存储Steing是唯一的,但在存储Student对象时不唯一?
Steing是系统写好的内部类,有equals与 hashCode方法,所以当我们使用时需要重写。
2,当Treeset存储String是有序的,但存储Student对象时却报异常(类型转化异常)?
在Student在threeSet下没有compareTo比较方法?
原因:String是系统类,做了一些其他操作,而student是自定义类,一些操作没有做
解决问题一:在Student类下重写equals与 hashCode方法(缺一不可)。
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Double.compare(student.score, score) == 0 &&
Objects.equals(name, student.name) &&
Objects.equals(sex, student.sex);
}
@Override
public int hashCode() {
return Objects.hash(name, sex, age, score);
}
现象:
解决问题2:在Student在threeSet下重写compareTo的比较方法(按照姓名比较),这样使用treeHash就不会报错了。
//重写TreeSet的比较规则
@Override
public int compareTo(Student other){
return this.name.compareTo(other.name);
}
报错显示:java.lang.ClassCastException: com.itheima.类名称 cannot be cast to java.lang.Comparable
在使用TreeSet时,发生的报错:原因就是在自定义类在ThreeSet下没有compareTo比较方法?
解决办法:
public class 自定义类 implements Comparable<Student> {
//重写TreeSet的比较规则
@Override
public int compareTo(自定义类 other){
return this.name.compareTo(other.属性);
}
以上是关于一篇文章让你精通:java集合讲解(三,Set)的主要内容,如果未能解决你的问题,请参考以下文章