------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
Set 接口特点:
不允许存储重复元素,无序集合:存储取出没有顺序(不保证迭代顺序),没有索引
Set接口方法,和父接口Collection抽象方法完全一样
Set接口存储对象并迭代,找实现类HashSet集合
- HashSet 如何保证元素唯一?
Set里的元素是不能重复的,使用 equals() 方法和 hashCode() 方法来区分重复与否。覆盖 equals() 方法、hashCode() 方法用来判断两个对象是否为同一对象,而“==”判断地址是否相等,用来决定引用值是否指向同一对象。
底层数据结构是哈希表,哈希表依赖于哈希值存储,添加功能底层依赖于两个方法 inthashCode(), boolean equals(Object obj) ,当存储对象时,先调用对象的 hashCode() 方法,校验哈希值是否与哈希表中已存在对象的哈希值相等,如果相等,当前对象调用 equals() 方法与表中已存在对象进行比较,如果结果是 true ,则哈希值一样,且比较结果为 true ,集合判断为同一对象不再存储。
如果两个对象,哈希值一样,equals一定返回 true 吗?不一定
如果两个对象,equals方法返回 true,拥有相同的哈希值吗?一定
HashSet特性:无序,不重复,无索引
底层数据结构是哈希表:数组 + 链表实现(元素是链表的数组)
存取速度都非常快,线程不安全集合,运行速度快
- HashMap 和 HashSet 有什么关系?
HashSet 底层是采用 HashMap 实现的。
privatetransient HashMap<E, object> map;
HashSet 类里面定义的一个私有成员变量。放进 HashSet 中的对象,其实是用这个HashMap 的 key 来存储的。当调用 HashSet 的 add 方法时,实际上是向 HashMap 中增加了一行 (key-value) 对,该行的 key 就是向 HashSet 增加的那个对象,该行的 value 就是一个 Object 类型的常量(静态的 Object 对象)。
LinkedHashSet特点:元素有序(由链表保证)唯一(由哈希表保证)
since JDK1.4 ,出现时间晚于 Set 接口和父类 HashSet
继承 HashSet
存储和取出的顺序是一致的
底层结构是基于哈希表的链表实现
线程不安全集合
Set 接口是无序的集合,而LinkedHashSet 变成有序集合。
TreeSet 集合的自身特性:
底层数据结构是红黑树(自平衡的二叉树),保证元素的排序和唯一性
线程不安全,运行速度快
对存储的对象进行排序:
自然顺序排序
(java.lang.Comparable,对实现类的对象进行强制排序)
自定义的对象的类 implementsComparable<> ,
重写接口中的 compareTo() 方法,建立自定义对象的自然顺序
根据创建集合时传递的比较器进行排序
自定义比较器 implements Comparator<> ,
重写接口中的 compare() 方法
TreeSet存储自定义对象
TreeSet集合存储对象时,不考虑hashCodeequals
- 1. TreeSet集合依据对象的自然顺序进行排序
要求存储到TreeSet集合中的对象,具有自然顺序
类实现Comparable接口,重写compareTo
2.TreeSet集合自己具备比较性
自定义比较器对象,实现java.util.Comparator,重写compare
接口实现类对象,传递给TreeSet集合
一旦有了比较器,TreeSet集合不考虑对象自然顺序
- HashSet 集合存储自定义对象并遍历(如果对象的成员变量值相同即为同一个对象)
package cn.itcast.set;
importjava.util.HashSet;
import java.util.Set;
/*
* HashSet存储自定义对象,不存储相同的元素
* 校验对象的唯一性
* 依赖于在自定义对象中重写hashCode 和 equals 两个方法实现
*/
public classHashSetDemo {
public static void main(String[] args) {
Set<Person> set = new HashSet<>();
set.add(new Person("zs", 20));
set.add(new Person("ls", 21));
set.add(new Person("zs", 20));
for (Person person : set) {
System.out.println(person);
}
// Person [name=ls, age=21]
// Person [name=zs, age=20]
}
}
- TreeSet 集合存储自定义对象并遍历
(如果对象的成员变量值相同即为同一个对象,按照年龄进行从大到小进行排序)
package cn.itcast.set;
import java.util.TreeSet;
publicclassTreeSetDemo {
publicstaticvoid main(String[] args) {
TreeSet<String>set= newTreeSet<String>();
set.add("www");
set.add("itcast");
set.add("cn");
for (String string : set) {
System.out.print(string + " ");
}
// cn itcast www 对存储的对象进行排序
System.out.println();
// 自然顺序比较
TreeSet<Person>set2= newTreeSet<Person>();
// 比较器比较
// TreeSet<Person>set2 = new TreeSet<Person>(new PersonComparator());
set2.add(new Person("zs", 20));
set2.add(new Person("ls", 21));
System.out.println(set2);
// [Person [name=ls, age=21], Person [name=zs, age=20]]
}
}
/*
* 重写接口compareTo方法,建立Person类自然顺序
*
* @seejava.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
publicint compareTo(Person o) {
intvalue = this.name.compareTo(o.name);
if (value == 0) {
returnthis.age - o.age;
}
returnvalue;
}
package cn.itcast.set;
import java.util.Comparator;
publicclassPersonComparator implements Comparator<Person>{
/*
* (non-Javadoc)
* @seejava.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
@Override
publicint compare(Person o1, Person o2) {
intvalue = o1.getAge() - o2.getAge();
if (value == 0) {
returno1.getName().compareTo(o2.getName());
}
returnvalue;
}
}
- 键盘录入 5 个学生信息,按照总分从高到低输出到控制台
package cn.itcast.set;
importjava.util.Scanner;
import java.util.Set;
importjava.util.TreeSet;
public class SetTest1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Set<StudentInfo> set = new TreeSet<StudentInfo>(new StudentScoreComparator());
for (int i = 0; i < 3; i++) {
String line = sc.nextLine();
String[] str = line.split(" +");
StudentInfo s = new StudentInfo(str[0],Integer.parseInt(str[1]), Integer.parseInt(str[2]),
Integer.parseInt(str[3]));
set.add(s);
}
for (StudentInfo studentInfo : set) {
System.out.println(studentInfo);
}
}
}
package cn.itcast.set;
import java.util.Comparator;
publicclassStudentScoreComparator implements Comparator<StudentInfo> {
@Override
publicint compare(StudentInfo o1, StudentInfo o2) {
intvalue = o1.getTotal() - o2.getTotal();
returnvalue == 0 ? o1.getName().compareTo(o2.getName()) : value;
}
}