Java第十三天(二)
Set
定义:一个不包含重复元素的Collection,并且最多只包含一个null元素。
特点:
①无序性(与添加顺序无关)
②元素唯一性(重复元素只存在一个)
③允许包含null元素,但只能存在一个
④不是线程安全的
Set中的方法全部继承于Collection,用法也与Collection一致,没有自己特有的方法。
HashSet
定义:此类实现Set接口,这个类提供了基本操作(add,remove,contains和size)。
无序性与元素唯一性
Set<String> set = new HashSet<String>();
set.add("赵一");
set.add("钱二");
set.add("张三");
set.add("李四");
set.add("王五");
set.add("王五");
System.out.println(set);
//使用增强for循环进行二次验证
for(String i:set) {
System.out.print(i+" ");
}
输出结果:
[李四, 张三, 王五, 钱二, 赵一]
李四 张三 王五 钱二 赵一
在Set中比较两个对象是否相等
步骤:
①现在成员变量类中重写父类Object的equals方法。
②使用if语句(instanceof)先判断对象是否与目标类对象的类型一致。
③将传递过来的对象强制转换成目标类对象的类型。
④再将各个成员变量进行比较(若存在字符串要先判断是否为空)。
⑤重写hashCode方法,使其值相等(返回相同的值)。
Set中判断两个对象是否相等,必须重写equals与hashCode方法,若这两个方法都符合相等的条件,才能判断这两个对象相等。
比较字符串类型的成员变量时,使用equals方法。
/*
* Student类
*/
public class Student {
//定义学生类成员变量
private int id;
private String name;
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//生成相应的构造器
public Student(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
//重写toString方法
@Override
public String toString() {
return "Student [学号=" + id + ", 姓名=" + name + ", 年龄=" + age + "]";
}
//重写equals方法
@Override
public boolean equals(Object obj) {
//判断是否为Student的对象
if(!(obj instanceof Student)) {
return false;
}
//由于被传过来的对象被转换为成Object类型,所以这里再转换回去
Student student = (Student)obj;
if(this.id == student.id &&
this.name != null && student.name != null &&
student.name.equals(this.name) &&
this.age == student.age) {
return true;
}else {
return false;
}
}
//重写hashCode方法
@Override
public int hashCode() {
return 1;
}
}
public static void main(String[] args) {
Set<Student> set = new HashSet<Student>();
set.add(new Student(1, "张三", 20));
set.add(new Student(2, null, 20));
set.add(new Student(1, "张三", 20));
System.out.println(set);
}
输出结果:
[Student [学号=1, 姓名=张三, 年龄=20], Student [学号=2, 姓名=null, 年龄=20]]
从上面的例子可以看出,虽然在Set中添加了三个对象,但实际打印出来只有两个对象。由于我们重写了方法的原因,所以有两个对象被判定为相等,而Set中虽然可以存在多个相等的元素,但只会选取其中的一个。
LinkedHashSet
其方法继承于HashSet,不同的是LinkedHashSet具有有序性。
特点:
①有序序性(根据元素的添加顺序进行排序)
②元素唯一性(重复元素只存在一个)
③允许包含null元素,但只能存在一个
④不是线程安全的
有序性
Set<String> set = new LinkedHashSet<String>();
set.add("赵一");
set.add("钱二");
set.add("张三");
set.add("李四");
set.add("王五");
set.add("王五");
System.out.println(set);
for(String i:set) {
System.out.print(i+" ");
}
输出结果:
[赵一, 钱二, 张三, 李四, 王五]
赵一 钱二 张三 李四 王五
TreeSet
TreeSet可以支持自定义排序。
当TreeSet内的元素都为同一种类型时,将自动进行排序(从小到大)。
如果TreeSet所存储对象的类没有实现Comparable接口就会报错(ClassCastException)。所以想要使用TreeSet来对自定义对象来排序的话必须实现Comparable接口。
当TreeSet内的元素为对象类型时,需要在对象类中实现Comparable接口,再自定义对象的排序规则(重写CompareTo方法)。
特点:
①元素唯一性
②可自定义排序
③不允许null元素存在
④不是线程安全的
String中的CompareTo方法
返回值类型 方法名 参数列表
int compareTo(String anotherString)
按字典顺序比较两个字符串。
例:
String str = "abc";
String str2 = "cde";
System.out.println(str.compareTo(str2));
输出结果:
-2
上面的返回-2是ASCII码中字母a减去字母c的值。
两个字符串相互比较时,实际比较的是字符的ASC值。
比较顺序是先从第一个字符开始比较,向后比较相同索引字符的ASCII码值。第一个字符的大小决定整个字符串的大小,若第一个字符相同,将依次比较相同索引的字符。
对象中的CompareTo方法
举例一(简单对象间比大小):
/*
* Student类
*/
public class Student implements Comparable<Student> {
//定义学生类成员变量
private int id;
private String name;
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//生成相应的构造器
public Student(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
//重写toString方法
@Override
public String toString() {
return "Student [学号=" + id + ", 姓名=" + name + ", 年龄=" + age + "]";
}
/**
* 重写Comparable方法
* 首先比较学号,按照学号升序进行排序
* 若学号相同,比较年龄,年龄小的在前
* 若学号、年龄都相同,比较姓名
*/
@Override
public int compareTo(Student stu) {
//先比较学号
int val = this.id - stu.id;
if(val == 0) {
//若学号相同比较年龄
val = this.age - stu.age;
if(val == 0) {
//判断两个对象的姓名是否为空
if(this.name != null && stu.name != null) {
//若学号、年龄都相同,比较姓名
val = this.name.compareTo(stu.name);
}
}
}
return val;
}
}
public static void main(String[] args) {
Set<Student> set = new TreeSet<Student>();
Student stu = new Student(1, "zhangsan", 20);
Student stu2 = new Student(3, "lisi", 20);
int i = stu.compareTo(stu2);
System.out.println(i > 0?"stu大":"stu1大");
}
输出结果:
stu1大
举例二(对象之间自定义排序):
继续使用举例一中的学生类
如果想要改变排序顺序只需改变学生类中 int val = this.id - stu.id;减数与被减数的顺序
public static void main(String[] args) {
Set<Student> set = new TreeSet<Student>();
set.add(new Student(1, "zhangsan", 20));
set.add(new Student(3, "lisi", 25));
set.add(new Student(2, "wangwu", 20));
System.out.println(set);
}
输出结果:
[Student [学号=1, 姓名=zhangsan, 年龄=20],
Student [学号=2, 姓名=wangwu, 年龄=20],
Student [学号=3, 姓名=lisi, 年龄=25]]
本文介绍了Java中的Set接口及其三种实现类:HashSet、LinkedHashSet和TreeSet。HashSet无序且保证元素唯一性,而LinkedHashSet保持插入顺序。TreeSet支持自定义排序,但不接受null元素。文章还详细讲解了如何通过重写equals和hashCode方法以及Comparable接口来实现对象在Set中的比较和排序。
1138

被折叠的 条评论
为什么被折叠?



