Set集合

一、Set集合的特点:

  1. java.util.Set接口 extends Collection接口
  2. 不允许存储重复的元素
  3. 没有索引,没有带索引的方法,也不能使用普通的for循环。(和Collection接口方法一样)

二、java.util.HashSet<E>

  1. java.util.HashSet集合 implements Set接口
  2. 不允许存储重复的元素
  3. 没有索引,没有带索引的方法,必须使用增强for循环。(和Collection接口方法一样)
  4. 是一个无序的集合(存储元素和取出元素的顺序可能不同)
  5. 底层实现是一个哈希表结构(查询速度非常快)

举例说明不允许存储重复的元素:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Set<Integer> set=new HashSet<>(); //生成一个set集合的对象
//使用add方法 //和Collection接口方法一样
set.add(1);
set.add(2);
set.add(3);
set.add(1);

//使用迭代器;
Iterator<Integer> set2=set.iterator();
while(set2.hasNext())
{
int s=set2.next();
System.out.println(s);
}

System.out.println("!!!!!!!!!!!"); //分隔符,比较和增强for循环的区别

//增强for循环
for(int i:set)
{
System.out.println(i); //set为上面set集合的对象
}

}
}

结果分析
1
2
3
!!!!!!!!!!!
1
2
3
(没有出现第四个重复的元素1!!!)


三、HashSet集合存储数据的结构(哈希表)
  哈希值:一个十进制的整数,由系统随机给出(对象的地址值,是一个逻辑地址,是模拟出来的地址,不是数据实际存储的物理地址)。
  在Object类有一个方法可以获取对象的哈希值:hashCode();

hashCode方法的源码:
public native int hashCode();
native:代表该方法调用的是本地操作系统的方法。

1
2
3
4
5
6
7
8
9
10
11
public class Main extends Object{  //写继承Object类更加明显看出是Object类的方法
public static void main(String[] args) {
Main i=new Main();
int a=i.hashCode(); //调用方法
System.out.println(a); //2018699554(逻辑地址)

Main j=new Main();
int b=j.hashCode(); //调用方法
System.out.println(b); //1311053135(逻辑地址)
}
}

toString方法的源码:
return getClass().getName()+”@”+Integer.toHexString(hashCode());  输出为“类名@十六进制数字”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Main extends Object {
public static void main(String[] args) {
Main i=new Main();
int a=i.hashCode();
System.out.println(a); //2018699554

Main j=new Main();
int b=j.hashCode(); //1311053135
System.out.println(b);

/*toString方法的源码:
return getClass().getName()+"@"+Integer.toHexString(hashCode()); //“类名@十六进制数字”
*/
System.out.println(i); //Main@7852e922
System.out.println(j); //Main@4e25154f

}
}

四、哈希表
jdk1.8版本之
  哈希表=数组+链表
jdk1.8版本之
  哈希表=数组+链表
  哈希表+数组+红黑树(提高查询速度)
数组结构相同哈希值的元素分为一组
链表结构//红黑树相同哈希值的元素连接一起

步骤:

  1. 将数据存储到集合中,先计算元素的哈希值。
  2. 然后按照哈希值将其放入不同的数组中,相同的就连接在一起。
  3. 如果连接的元素>=8 —-链表->红黑树(一层红色结点,一层黑色结点)


五、Set集合存储元素不重复的原理

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.*;
public class Main extends Object{
public static void main(String[] args) {
HashSet<String> set=new HashSet<>();
String s1=new String("abc");
String s2=new String("abc");
set.add(s1); //会调用元素的hashCode方法和equals方法判断是否重复
set.add(s2);
set.add("重地");
set.add("通话");
set.add("abc");
System.out.println(set); //只输出 [重地, 通话, abc]
}
}

结果分析:
set.add(s1);  
  add方法调用s1的hashCode方法 -> 计算字符串”abc”的哈希值(96354) -> 在集合中找是否有96354这个哈希值的元素 -> 没有就把s1存储到集合中

set.add(s2); 
  add方法调用s2的hashCode方法 -> 计算字符串”abc”的哈希值(96354) -> 在集合中找是否有96354这个哈希值的元素 -> 有就是哈希冲突(值相同,元素不同) -> 调用s2.equals(s1)返回true  -> 不会将s2存储到集合中

set.add("重地");
  add方法调用”重地”的hashCode方法 -> 计算字符串”重地”的哈希值(1179395) -> 在集合中找是否有1179395这个哈希值的元素 -> 没有就把”重地”存储到集合中

set.add("通话");
  add方法调用”通话”的hashCode方法 -> 计算字符串”通话”的哈希值(1179395) -> 在集合中找是否有1179395这个哈希值的元素 -> 有就是哈希冲突(值相同,元素不同) -> “通话”.equals(“重地”)返回false -> 将”通话”存储到集合中


六、HashSet存储自定义类型元素

必须重写HashSet()和equals()方法。


七、LinkedHashSet<E>
LinkedHashSet集合(具有可预知的迭代顺序) extends HashSet集合(具有可预知的迭代顺序)

  1. 底层实现是一个哈希表结构(查询速度非常快)
  2. 哈希表=数组+链表/红黑树+链表(记录元素的存储顺序)

例子:

1
2
3
4
5
6
7
8
9
10
11
import java.util.*;
public class Main extends Object{
public static void main(String[] args) {
LinkedHashSet<String> set=new LinkedHashSet<>();
set.add("www");
set.add("abc");
set.add("abc");
set.add("itcast");
System.out.println(set); //输出[www, abc, itcast]
}
}

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
,