java–基础–9.5–集合–set
1、Collection 接口
Collection 接口
|--List 接口,继承Collection
|--ArrayList --- implement List
|--Vector --- implement List
|--LinkedList --- implement List
|--Set 接口,继承Collection
|--HashSet --- implement Set
|--linkedHashSet 继承HashSet
|--TreeSet --- implement Set
2、set集合
- 无序
- 唯一
2.1、子类
- HashSet
- LinkedHashSet
- TreeSet
3、HashSet
- 底层数据结构是哈希表(是一个元素为链表的数组)
- 哈希表底层依赖两个方法:hashCode()和equals(),该方法与添加的对象有关,所以添加的对象需要重写hashCode()和equals()
3.1、构造方法
3.2、add方法的底层实现,可以说明为什么set的值是唯一,不重复的
//key 是add添加的对象
public V put(K key, V value) { //key=e=hello,world
//看哈希表是否为空,如果空,就开辟空间
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
//判断对象是否为null
if (key == null)
return putForNullKey(value);
int hash = hash(key); //和对象的hashCode()方法相关
//在哈希表中查找hash值
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
//table[i] 获取哈希表中的对象
Object k;
//比较add添加的对象与哈希表的对象
//如果哈希值相同,且(两者地址值相同或者内容相同),就不添加元素,否则就添加元素
//比较地址值或者走equals()
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;//跳出方法,不走下面的代码
}
}
modCount++;
addEntry(hash, key, value, i); //把元素添加
return null;
}
4、LinkedHashSet:
底层数据结构由哈希表和链表组成。
哈希表保证元素的唯一性链表保证元素有素。(存储和取出是一致)
5、、TreeSet
- 能够对元素按照某种规则进行排序。
- 排序和唯一
- 底层数据结构是二叉树
5.1、构造方法
5.2、自然排序
让元素所属的类实现Comparable接口,基本类型都有实现该接口,自定义类需要自己实现该接口。
5.2.1、基本类型的自然排序
// 创建集合对象
// 自然顺序进行排序
TreeSet<Integer> ts = new TreeSet<Integer>();
ts.add(5);
ts.add(4);
ts.add(2);
ts.add(3);
ts.add(1);
// 遍历
for (Integer i : ts) {
System.out.println(i);
}
输出:
1
2
3
4
5
5.2.2、自定义类的自然排序
自定义类
package cn;
/*
* 如果一个类的元素要想能够进行自然排序,就必须实现自然排序接口
*/
public class Student implements Comparable<Student> {
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
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(Student s) {
//按照年龄排序
int num1= this.getAge()-s.getAge();
如果年龄相同,按名字排序
int num2=num1==0?(this.getName().compareTo(s.getName())):num1;
return num2;
}
}
自定义类的自然排序测试
// 创建集合对象
TreeSet<Student> ts2 = new TreeSet<Student>();
// 创建元素
Student s1 = new Student("abc", 27);
Student s2 = new Student("abc", 29);
Student s3 = new Student("bcd", 23);
Student s4 = new Student("efd", 27);
Student s5 = new Student("cfd", 22);
Student s6 = new Student("cdf", 40);
Student s7 = new Student("bed", 22);
// 添加元素
ts2.add(s1);
ts2.add(s2);
ts2.add(s3);
ts2.add(s4);
ts2.add(s5);
ts2.add(s6);
ts2.add(s7);
// 遍历
for (Student s : ts2) {
System.out.println(s.getName() + "---" + s.getAge());
}
输出:
bed---22
cfd---22
bcd---23
abc---27
efd---27
abc---29
cdf---40
5.3、底层2叉数分析:
5.3.1、比较器排序
让TreeSet< T t>接收Comparator的实现类对象
举例:
new TreeSet< T t>(Comparator的实现类对象)
new TreeSet< T t>(new Comparator<T>(){ 重写compare方法,定义规则})
案例
// 比较器进行排序
System.out.println("------------比较器进行排序--------------------");
TreeSet<Student> tComparator = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// 姓名排序
int num = s1.getName().compareTo(s2.getName());
// 年龄排序
int num2=num==0 ? s1.getAge() - s2.getAge():num;
return num2;
}
});
// 添加元素
tComparator.add(s1);
tComparator.add(s2);
tComparator.add(s3);
tComparator.add(s4);
tComparator.add(s5);
tComparator.add(s6);
tComparator.add(s7);
// 遍历
for (Student s : tComparator) {
System.out.println(s.getName() + "---" + s.getAge());
}
输出:
------------比较器进行排序1--------------------
abc---27
abc---29
bcd---23
bed---22
cdf---40
cfd---22
efd---27