Set接口 Extends Collection接口
Set接口特点:
- Set接口不允许
- 没有索引
HashSet集合 implements set接口
-
不允许存储重复的元素
-
没有索引,没有索引的方法,也不能使用普通的for循环遍历
-
是一个无序的集合,存储元素和取出元素的顺序有可能不一致
-
底层是一个哈希表结构(查询速度非常快)
import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class HashSetMode2 { public static void main(String[] args) { Set<Integer> set = new HashSet<>(); set.add(1); set.add(2); set.add(1); Iterator<Integer> it = set.iterator(); while(it.hasNext()){ Integer n = it.next(); System.out.println(n); } } } //输出的只有1,2因为Set集合不允许存储重复元素
HashSet表:
哈希值:是一个十进制的整数,有系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来的,不是数据实际存储的物理地址,在Object类有一个方法,可以获取对象的Hash值)
int hashCode()返回该对象的哈希码值
native:代表该方法调用的是本地操作系统的方法
//Person类中
public class Person extends Object{
//重写hashCode方法
@Override
public int hashCode(){
retrun 1;
}
}
public class HashCodeMode1 {
public static void main(String[] args) {
Person p1 = new Person();
int h1 = p1.hashCode();
System.out.println(h1);
Person p2 = new Person();
int h2 = p2.hashCode();
System.out.println(h2);
System.out.println(p1==p2);
System.out.println(p1);
System.out.println(p2);
}
}
/*
1
1
false
com.yu.Set.Person@1
com.yu.Set.Person@1
*/
String类的哈希值
//主函数中输出
public class HashCodeMode1 {
public static void main(String[] args) {
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s1 == s2);
}
}
/*
96354
96354
false
*/
哈希表结构:
jdk1.8版本之前:
- 哈希表=数组+链表
jdk1.8版本之后:
- 哈希表=数组+链表;
- 哈希表=数组+红黑树(提高查询的速度快)
哈希表的特点就是查询速度快
哈希冲突:两个元素不同,但是哈希值相同
若果链表的长度超过了8位,那么就会把链表转换为红黑树(为了提高查询的速度)
Set集合不允许存储重复元素的原理
前提:存储的元素必须重写hashCode方法和equals方法。
import java.util.HashSet;
public class SetDemo01 {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
String s1 = new String("abc");
String s2 = new String("abc");
set.add(s1);
set.add(s2);
set.add("你好!");
set.add("abc");
System.out.println(set);
}
}
/*
[你好!, abc]
*/
set.add(s1);
add方法会调用s1的hashCode方法计算字符串“abc”的哈希值,发现此地址 没有存放元素就会把s1存储到集合当中去。
set.add(s2);
add方法会调用s2的hashCode方法计算字符串"abc"的哈希值,发现此地址 已经存放元素(哈希冲突),就会调用equlas方法的哈希值相同的元素进行 比较,返回结果为true,就不会把s2储存到集合中。
set.add(“你好!”);
同理,add方法会调用hashCode方法计算法字符串的哈希值,发现此哈希 值地址没有存放元素,就会把元素存储到集合当中。
LinkedHashSet集合
LinkedHashSet集合特点:
底层是一个哈希表(数组+链表/红黑树)+链表:多了一层链表(用来记录 元素的存储顺序),保证元素有序
import java.util.HashSet;
public class LinkedHashSetDemo01 {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("abc");
set.add("123");
set.add("!@#");
System.out.println(set);
}
}
/*
[123, abc, !@#]
*/
//结果是无序的
import java.util.LinkedHashSet;
public class LinkedHashSetDemo01 {
public static void main(String[] args) {
LinkedHashSet<String> set = new LinkedHashSet<>();
set.add("abc");
set.add("123");
set.add("!@#");
System.out.println(set);
}
}
/*
[abc, 123, !@#]
*/
//LinkedHashSet集合输出的结果是有序的,不允许重复
可变参数
jdk1.5之后出现的新特性。
使用前提:
当方法的参数列表数据类型已经确定,但是传递的参数的个数不确定就可以 使用可变参数。
使用格式:定义方法时使用
修饰符 返回值类型 方法名(数据类型…变量名){}
public static int add(int...arr){}
可变参数的原理:
可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数 组,来存储这些参数,传递的参数个数可以是0个(即不传递从参数),1,2… 多个。
可变参数注意事项:
-
一个方法的参数列表,只能有一个可变参数。(数据类型不同也不行)
-
如果方法的参数有多个,那么可变参数必须写在参数列表的末尾。
public static void method(String a,double b,int...c){}
可变参数的特殊写法:
public static void method(Object...obj){}