Set集合:
1.hashSet
2.linkedHashSet
3.TreeSet
1.1Set集合概述和特点:
1.1.1 元素无序性和唯一性
唯一性:add
boolean add(E e)如果 set 中尚未存在指定的元素,则添加此元素(可选操作)。更确切地讲,如果此 set 没有包含满足 (e=null ? e2==null : e.equals(e2)) 的元素 e2,则向该 set 中添加指定的元素 e。如果此 set 已经包含该元素,则该调用不改变此 set 并返回 false。结合构造方法上的限制,这就可以确保 set 永远不包含重复的元素。
上述规定并未暗示 set 必须接受所有元素;set 可以拒绝添加任意特定的元素,包括 null,并抛出异常,这与 Collection.add 规范中所描述的一样。每个 set 实现应该明确地记录对其可能包含元素的所有限制。
1.2HashSet存储字符串并遍历
public class MyTest {
public static void main(String[] args) {
//Set:元素唯一
// HashSet 底层数据结构是哈希表(数组+链表 JDK1.7 JDK1.8 数组+链表+二叉树)
//HashSet 元素无序(存取顺序不一致),且唯一(元素不能重复)
//哈希表像新华字典
// LinkedHashSet
//TreeSet
HashSet<String> set = new HashSet<>();
set.add("aaa");
set.add("bbb");
set.add("ccc");
set.add("刘德华");
set.add("郭富城");
set.add("黎明");
set.add("张学友");
set.add("刘德华");
set.add("郭富城");
set.add("黎明");
set.add("张学友");
for (String s : set) {
System.out.println(s);
}
}
}
1.3HashSet保证元素唯一性
理解:HashSet 底层数据结构是哈希表. HashSet 不是线程安全的 集合元素可以是 null
哈希表:是一个元素为链表的数组,综合了数组和链表的优点 (像新华字典一样) (JDK1.7之前)
原因:
当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,
然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。
HashSet 集合判断两个元素相等的标准:
两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。
结论:HashSet 保证元素唯一性是靠元素重写hashCode()和equals()方法来保证的,如果不重写则无法保证。
1.4存储对象保证唯一性图解
1.5HashSet存储自定义对象并遍历练习
案例演示:
public class MyTest2 {
public static void main(String[] args) {
HashSet<Integer> integers = new HashSet<>();
integers.add(100);
integers.add(1);
integers.add(200);
integers.add(100);
integers.add(2);
integers.add(300);
integers.add(200);
integers.add(100);
integers.add(2);
for (Integer integer : integers) {
System.out.println(integer);
}
}
}
1.6LinkedHashSet的概述和使用
数据结构的特点:
数据结构 有两个 链表和哈希表
链表保证有序 哈希表保证元素唯一,线程不安全效率高。
案例演示:
public class MyTest2 {
public static void main(String[] args) {
// new LinkedHashSet,数据结构为String类型
LinkedHashSet<String> strings = new LinkedHashSet<>();
strings.add("aaa");
strings.add("bbb");
strings.add("ccc");
strings.add("ddd");
strings.add("eee");
strings.add("fff");
strings.add("aaa");
strings.add("bbb");
strings.add("ccc");
strings.add("ddd");
strings.add("eee");
strings.add("fff");
//遍历(使用新遍历方式)
for (String string : strings) {
System.out.println(string);
}
1.7TreeSet存储Integer类型的元素并遍历
public class TreeSetDemo {
public static void main(String[] args) {
// TreeSet 元素唯一,且可以对元素进行排序
//底层数据结构是二叉树
//排序:自然排序,比较器排序
// 20, 18, 23, 22, 17, 24, 19, 18, 24
TreeSet<Integer> treeSet = new TreeSet<>();
treeSet.add(20);
treeSet.add(18);
treeSet.add(23);
treeSet.add(22);
treeSet.add(17);
treeSet.add(24);
treeSet.add(19);
treeSet.add(18);
treeSet.add(24);
System.out.println(treeSet);
}
}
1.8排序
应用:
排序:自然排序 和 比较器排序
自然排序:如果采用的是空参构造,那么采用的就是自然排序
如果是自然排序,那么对元素有要求,要求元素必须实现一个Comparable接口,重写这个接口中的一个compareTo这个比较的方法。
//构造一个新的空 set,该 set 根据其元素的自然顺序进行排序。
// TreeSet
// 自然排序,使用空参构造,他的要求就是元素必须实现 Compareble接口,重写compareTo方法 ,根据此方法的返回值的正 负 0 来决定元素的放置位置
//比较器排序:采用有参构造,你在创建TreeSet对象时,需要传入一个Comparetor 比较器
//TreeSet(Comparator < ? super E > comparator)
//构造一个新的空 TreeSet,它根据指定比较器进行排序。
//Comparator<T> 比较器
//int compare (T o1, T o2)
//比较用来排序的两个参数。
自然排序
案例演示1
空参构造用自然啊排序:
public class Student implements Comparable<Student> {
private String name;
private int age;
public Student() {
}
public Student(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 String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//这是一个比较的方法
@Override
public int compareTo(Student student) {
//根据学生的年龄大小来排序
//年龄一样,并不能说明是同一个对象,我们还得比较姓名是否一样
int num=this.age-student.age;
int num2=num==0?this.name.compareTo(student.name):num;
return -num2; //根据返回值的正 负 0 来决定元素的放置位置
}
}
以上先是写一个Student类。再写一个测试类:
public class MyTest {
public static void main(String[] args) {
TreeSet<Student> treeSet = new TreeSet<>();
treeSet.add(new Student("张三士大夫士大夫", 23));
treeSet.add(new Student("张三是非得失", 23));
treeSet.add(new Student("李四大幅度发", 23));
treeSet.add(new Student("王五大幅度发", 20));
treeSet.add(new Student("周六的", 30));
treeSet.add(new Student("田七大幅度", 23));
treeSet.add(new Student("李白大幅度发", 33));
treeSet.add(new Student("刘星大幅度发", 63));
treeSet.add(new Student("夏雨", 78));
treeSet.add(new Student("张子豪", 53));
//排序:自然排序 和 比较器排序
//自然排序:如果采用的是空参构造,那么采用的就是自然排序
//如果是自然排序,那么对元素有要求,要求元素必须实现一个Comparable接口,重写这个接口中的一个compareTo这个比较的方法
//***根据此方法的返回值的正 负 0 来决定元素,排列的位置***
for (Student student : treeSet) {
System.out.println(student);
}
}
}
案例演示2
有参构造用选择器排序
先创建一个Student类如上代码所示,只不过不构造方法,不重写。
在创建一个测试类:
public class MyTest {
public static void main(String[] args) {
//TreeSet()
MyComparator myComparator = new MyComparator();
TreeSet<Student> treeSet = new TreeSet<>(myComparator);
treeSet.add(new Student("张三士大夫士大夫", 23));
treeSet.add(new Student("张三是非得失", 23));
treeSet.add(new Student("李四大幅度发", 23));
treeSet.add(new Student("王五大幅度发", 20));
treeSet.add(new Student("周六的", 30));
treeSet.add(new Student("田七大幅度", 23));
treeSet.add(new Student("李白大幅度发", 33));
treeSet.add(new Student("刘星大幅度发", 63));
treeSet.add(new Student("夏雨", 78));
treeSet.add(new Student("张子豪", 53));
for (Student student : treeSet) {
System.out.println(student);
}
}
}