一、Set接口的特点
Set接口的特点是:元素无序,且值唯一(值不允许重复)
二、Set接口的具体实现类
1、HashSet类
(1)HashSet类的特点
元素无序,且值不允许重复
(2)HashSet类的数据结构
HashSet类的数据结构是:HashMap(HashSet相当于一个只存储Key,不存储Value(在每个HashMap的Value的位置都存储一个PERSON常量)的特殊Map。放入Set的元素和Map的Key特点类似,不允许重复),下图为HashSet的源码
(3)HashMap的常用方法
<1>add()添加新元素
HashSet<String> set=new HashSet<String>;
//HashSet的特征一:元素不允许重复
boolean isAdd1=set.add("1.小乔");
System.out.println(isAdd1);
boolean isAdd2=set.add("2.大乔");
System.out.println(isAdd2);
boolean isAdd3=set.add("1.小乔");
System.out.println(isAdd3);
输出结果:
true
true
false
//isAdd3和isAdd1的值完全相同,故isAdd3的值“1.小乔”添加失败,返回false.体现了HashSet的“值不允许重复”的特点。
<2>addAll()方法
//特征二:无序
set.add("1.小乔");
set.add("2.大乔");
set.addAll(Arrays.asList("3.曹操","4.许诸","5.张辽","6.赵云","7.典韦","8.夏侯惇"));
System.out.println(set);
输出结果:
[1.小乔, 7.典韦, 5.张辽, 4.许诸, 8.夏侯惇, 2.大乔, 3.曹操, 6.赵云]
//由输出结果可知,set中元素的顺序和我们添加的顺序并不一样,这就体现了HashSet“无序”的特点。
<3>remove()方法
set.addAll(Arrays.asList("1.小乔","2.大乔","3.曹操","4.许诸","5.张辽","6.赵云","7.典韦","8.夏侯惇"));
System.out.println(set);
set.remove("1.小乔");
System.out.println(set);
输出结果:
[1.小乔, 7.典韦, 5.张辽, 4.许诸, 8.夏侯惇, 2.大乔, 3.曹操, 6.赵云]
[7.典韦, 5.张辽, 4.许诸, 8.夏侯惇, 2.大乔, 3.曹操, 6.赵云]
<4>contains()方法
//接上述代码
boolean isContains=set.contains("1.小乔");
System.out.println(isContains);
输出结果:false
(4)Set的遍历
<1>基于迭代器的遍历
//基于迭代器的遍历
HashSet<String> set=new HashSet<String>();
set.addAll(Arrays.asList("3.曹操","4.许诸","5.张辽","6.赵云","7.典韦"));
//创建一个迭代器对象
Iterator<String> it=set.iterator();
While(it.hasNext()){
String item=it.next();
System.out.println(item);
}
输出结果:
7.典韦
5.张辽
4.许诸
3.曹操
6.赵云
<2>foreach遍历
HashSet<String> set=new HashSet<String>();
set.addAll(Arrays.asList("3.曹操","4.许诸","5.张辽","6.赵云","7.典韦"));
//foreach遍历
for(String name:set){
System.out.println(name);
}
输出结果:
7.典韦
5.张辽
4.许诸
3.曹操
6.赵云
2、LinkedHashSet类
(1)LinkedHashSet类的特点
元素有序,且值不允许重复
(2)LinkedHashSet类的数据结构
LinkedHashSet类的数据结构是:LinkedHashMap
(3)HashSet类和LinkedHashSet类对比
<1>有序or无序
//HashSet
HashSet<String> set1=new HashSet<String>();
set1.addAll(Arrays.asList("3.曹操","4.许诸","5.张辽","6.赵云","7.典韦"));
System.out.println(set1);
//LinkedHashSet
LinkedHashSet<String> set2=new LinkedHashSet<String>();
set2.addAll(Arrays.asList("3.曹操","4.许诸","5.张辽","6.赵云","7.典韦"));
System.out.println(set2);
输出结果:
[7.典韦, 5.张辽, 4.许诸, 3.曹操, 6.赵云]
[3.曹操, 4.许诸, 5.张辽, 6.赵云, 7.典韦]
//由输出结果可以看出,LinkedHashSet中元素的顺序和我们存入的顺序相同,而HashSet中元素的顺序与我们存入的顺序不同。
<2>值可重复or不可重复
HashSet和LinkedHashSet中的值均不允许重复
String s="莺莺燕燕鸟鸟花海";
//HashSet
HashSet<String> set1=new HashSet<String>();
//遍历set1
for(int i=0;i<s.length();i++){
//一个一个的取出s中的字符
String str=s.substring(i,i+1);
set1.add(str);
}
System.out.println(set1);
//LinkedHahSet
LinkedHahSet<String> set2=new LinkedHahSet<String>();
//遍历set2
for(int i=0;i<s.length();i++){
//一个一个的取出s中的字符
String str=s.substring(i,i+1);
set2.add(Str);
}
System.out.println(set2);
输出结果:
[花, 燕, 海, 莺, 鸟] //无序
[莺, 燕, 鸟, 花, 海] //有序
3、TreeSet类
(1)TreeSet类的特点
元素自动排序,且值不允许重复
(2)TreeSet类的数据结构
TreeSet类的数据结构是:TreeMap
(3)TreeSet的应用
//TreeSet集合内部使用TreeMap作为存储结构,所以在遍历TreeSet时,输出元素的顺序是经过排序的。按照元素的不同比较方式进行排序。所以,添加元素必须正确实现Comparable接口,如果没有实现Comparable接口,那么创建TreeSet时必须传入一个Comparator对象
String[] ans = {"ABC","AB","ABCD","A","DEF","BCD","AC",
"BCD","ABCDE","B","AD","A","BCD","ABCD"};
//需求1:过滤重复字符串
//需求2:自动排序(先按长度比较,如果长度相同,再按内容比较)
//构造方法,允许传入一个Comparator比较器
TreeSet<String> set=new TreeSet<String>(new Comparator<String>(){
public int compare(String o1, String o2) {
if(o1.length()!=o2.length()) {
//按照长度比较
return o1.length()-o2.length();
}else {
//按内容比较
return o1.compareTo(o2);
}
}
});
for(String s:ans) {
set.add(s);
}
for(String s:set) {
System.out.println(s);
}
输出结果:
A
B
AB
AC
AD
ABC
BCD
DEF
ABCD
ABCDE
三、Hash值的计算
int hash=646454;//哈希值
int n=16;//数组长度(必须是2的n次幂)
//计算hash值
//方法1:
int index1=hash%16;
//方法2:
int index2=(n-1)&hash;
System.out.println(index1);
System.out.println(index2);
输出结果:
6
6