三.Set
特点: 无序的(放入与输出的顺序不一致), 不可重复
1.HashSet
1.1基本用法
HashSet是一种哈希算法的集合
-
数据结构: 哈希表,哈希散列表
-
特点 :操作速度快,根据哈希算法快速定位元素的存放位置
HashSet<String> set = new HashSet<String>();
set.add("aaa");
set.add("bbb");
set.add("ccc");
set.add("ddd");
set.add("aaa");// 相同元素不会添加到集合中
System.out.println(set);
/**
* set集合
* add() size() remove 等都有,但是没有关于填入下标的方法
* set集合不能用下标访问,不能使用 普通的for循环进行遍历
*/
for (String s : set) {
System.out.println(s);
}
// addAll 添加一个集合 --- 可以用对list集合进行去重 list集合转为 了set集合
List<String> list = Arrays.asList(new String[]{"a","b","c","d","d","a"});
set.addAll(list);
System.out.println(set);
//使用构造方法将 list转为set集合
HashSet<String> set2 = new HashSet<String>(list);
System.out.println(set2);
1.2 HashSet如何判重
-
添加元素时,调用该对象的hashcode()方法,获取一个哈希值
-
根据哈希值,使用哈希算法确定一个哈希表中的位置
-
如果该位置没有元素,则直接放入
-
如果该位置有元素了,则调用两个对象的equals方法进行比较
true: 则认为是同一个对象,无法添加,舍弃当前对象
false:则认为不是同一个对象,以链式结构向当前位置进行追加,改变了哈希表的结构,会影响性能。
总结:
- 判断重复的依据,两个对象hashCode值一致,并且equals也返回true ---- 同一个对象—集合中只能添加一个进去
- 在set集合中防止相同对象被添加,需要 hashCode 和 equals都 重写
package javaSE13_Set集合;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
public class Test01_HashSet {
public static void main(String[] args) {
Test01_HashSet t = new Test01_HashSet();
// t.test1();
t.test2();
}
/**
* 基本用法
*/
public void test1(){
HashSet<String> set = new HashSet<String>();
set.add("aaa");
set.add("bbb");
set.add("ccc");
set.add("ddd");
set.add("aaa");// 相同的元素不会添加到集合中
System.out.println(set);
/**
* add() size() remove 等方法都有,
* 但 与下标相关方法都没有
* set集合不能有下标访问,不能使用普通循环进行遍历
*/
for (String s : set) {
System.out.println(s);
}
// addAll() 添加一个集合 -- 可用对list集合进行去重
List<String> list =Arrays.asList(new String[]{"a","b","c","d","a","b"});
set.addAll(list);
System.out.println(set);
//使用构造方法 将list转为set
HashSet< String> set2 = new HashSet<String>(list);
System.out.println(set2);
}
/**
* HashSet 判断重复的标准
*/
public void test2(){
HashSet<Student> set = new HashSet<Student>();
Student s1 = new Student(1001, "tom");
Student s2 = new Student(1001, "tom");
System.out.println(s1.equals(s2));
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
set.add(s1); set.add(s2);
System.out.println(set);
/**
* 如果认为学号 名字都一样,就是同一个学生,只需要添加一个到集合中
* 需要重写eq方法 和hashCode()
*/
}
}
2.TreeSet
2.1基本用法
用于对元素排序的有序集合
- 数据结构:二叉树
- 特点:元素有大小顺序
2.2排序
排序:
-
元素会根据自然顺序排列
存入的元素不具有自然顺序 ,集合会报错 ----- 该对象不可比较
解决: 让元素可以比较,将要比较的对象实现一个Comparable接口,表示该类型的对象可以比较
并且重写compareTo()方法,指定具体的比较规则
-
提供一个比较器,根据比较器进行排序
定义一个比较器,就是定义一个实现了Compartor 接口的类,实现compare()方法
在创建集合是,将比较器传入。
package javaSE13_Set集合;
import java.util.Comparator;
import java.util.TreeSet;
public class Test02_TreeSet {
public static void main(String[] args) {
Test02_TreeSet t = new Test02_TreeSet();
// t.test01();
t.test02();
}
public void test01(){
TreeSet<Integer> set = new TreeSet<Integer>();
TreeSet<String> set2 = new TreeSet<String>();
set.add(1);
set.add(15);
set.add(79);
set.add(4);
set.add(56);
set.add(0);
set2.add("abde");
set2.add("fjek");
set2.add("hueij");
set2.add("aaeie");
set2.add("djeju");
System.out.println(set);
System.out.println(set2);
}
public void test02(){
//1.引用类型要能够比较大小,实现Comparable接口,并在compareTo方法中指定比较的规则
TreeSet<User> set = new TreeSet<User>();
set.add(new User(1, "aa", 12));
set.add(new User(2, "bb", 15));
set.add(new User(3, "cc", 2));
set.add(new User(4, "dd", 15));
set.add(new User(5, "ee", 34));
// System.out.println(set);
//2.通过比较器对set集合进行排序
// A: 创建实现类
/*MyComparator c = new MyComparator();//new一个比较器对象
//set2集合的排序按照 c这个比较器对象中定义的规则排序
TreeSet<User2> set2 = new TreeSet<User2>(c);*/
// B: 直接创建的是接口,匿名内部类的写法,就不需要单独创建一个实现类
/* Comparator<User2> c = new Comparator<User2>(){
//定义比较的规则
@Override
public int compare(User2 u1, User2 u2) {
int i = u1.getAge() - u2.getAge();
if(i==0){
i=u1.getId() - u2.getId();
}
return i;
}
};
TreeSet<User2> set2 = new TreeSet<User2>(c);*/
// C: 再简化
TreeSet<User2> set2 = new TreeSet<User2>(new Comparator<User2>() {
@Override
public int compare(User2 u1, User2 u2) {
int i = u1.getAge() - u2.getAge();
if(i==0){
i=u1.getId() - u2.getId();
}
return i;
}
});
set2.add(new User2(1, "aa", 12));
set2.add(new User2(2, "bb", 15));
set2.add(new User2(3, "cc", 2));
set2.add(new User2(4, "dd", 15));
set2.add(new User2(5, "ee", 34));
System.out.println(set2);
}
}
package javaSE13_Set集合;
import java.util.Comparator;
/**
* 是一个比较器 : 就是一个实现了Comparator接口的类
* @author wenwen
*
*/
public class MyComparator implements Comparator<User2>{
//定义比较的规则
@Override
public int compare(User2 u1, User2 u2) {
int i = u1.getAge() - u2.getAge();
if(i==0){
i=u1.getId() - u2.getId();
}
return i;
}
}
注意:TreeSet判断重复的依据: 但添加的两个元素的compareTo() 或者 是 compare()方法 返回0时,就认为两个对象相同了,只会添加一个到集合中
package javaSE13_Set集合;
public class User implements Comparable<User>{
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 User() {
super();
// TODO Auto-generated constructor stub
}
public User(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + "]\n";
}
/**
* 自定义比较的规则
* 如果 按照 从小到大的顺序
* 负数: 小于
* 0: 等于
* 正数:this 为 大于
*/
/*@Override
public int compareTo(User o) {
//根据年龄进行比较 如果年龄相同 则继续按照另一个属性排序
if(this.age>o.getAge()){// this.age-o.getAge 是个正数
return 1;
}else if(this.age < o.getAge()){
return -1;
}else{
//年龄相同,id继续排
if(this.id > o.getId()){
return 1;
}else if(this.id<o.getId()){
return -1;
}else{
//如果 id继续相等,按照 姓名排
// 如果 比较的是字符串,直接调用字符串的比较方法
return this.name.compareTo(o.getName());
}
}
}*/
@Override
public int compareTo(User o) {
int i = this.age - o.getAge();
if(i==0){
i=this.id - o.getId();
if(i==0){
i=this.name.compareTo(o.getName());
}
}
return i;
}
}
package javaSE13_Set集合;
public class User2 {
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 User2() {
super();
// TODO Auto-generated constructor stub
}
public User2(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + "]\n";
}
}