- java.util.Set接口extends Collection
- Set接口的特点:
- 不允许存储重复的元素(原理与下方的HashSet相同)
- 没有索引,没有带索引的方法,不能使用普通的for循环遍历(用迭代器或 者增强for循环进行遍历)
- Set的方法
- boolean add(E e) 添加元素,但重复元素不会被添加成功
- void clear() 清空集合
- boolean contains(Object o) 判断 o 是否在集合中
- Iterator iterator() 返回迭代器
- boolean remove(Object o) 删除集合中的 o
- Set纯K模型:Set
HashSet java.util
- .HashSet集合的特点:
- 没有索引,没有带索引的方法,不能使用普通的for循环遍历(用迭代器或者增强for循环进行遍历)
//迭代器遍历
Iterator<Integer>it=set.iterator();
while(it.hasNext()){
Integer n=it.next();
System.out.printf("%d ",n);
}
//增强for遍历
for (Integer i : set) {
System.out.printf("%d ",i);
}
- 不允许存储重复的元素(原理如图)–底层重写啦hashCode方法和equals方法(必须重写,才能保证存储的元素不重复)
- 是一个无序集合,存储元素和取出元素的顺序可能不一致
- 哈希表结构;没有顺序,无序集合
运行结果分析:很明显,重复的1没有被存入进去,且存储元素与取出元素的顺序不一
HashSet存储结构:哈希表
- 1.8之前:数组+链表
- 1.8之后: 数组+链表(当链表长度超过8位时,将链表转换位红黑树)
数组+红黑树(提高查询速度)
HashSet存储自定义类型:
Set报错元素唯一:
存储的元素(string,Integer,…,Person,Student),必须重写hashCode方法和 equals方法
要求:同名同年龄视为同一人,只能存储一次
1.未重写hashCode方法和equals方法
import java.util.Objects;
/**
* @author yolo
* @date 2019/10/11-22:15
*/
public class Person {
int age;
String name;
public Person() {
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
public static void main(String[] args) {
HashSet<Person>hashSet=new HashSet<>();
Person p1=new Person(18,"小美女");
Person p2=new Person(18,"小美女");
Person p3=new Person(19,"小美女");
hashSet.add(p1);
hashSet.add(p2);
hashSet.add(p3);
System.out.println(hashSet);
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
}
2.重写啦hashCode方法和equals方法(必须重写,才能保证存储的元素不重复)
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(age, name);
}
LinkedHashSet
- java.util.LinkedHashSet集合extends HashSet集合
- LinkedHashSet集合特点:
- 底层是一个哈希表(数組+链表/红黑树)+链表:
- 多了条链表(记录元素的存储顺序),保证元素有序(与Set和HashSet不同)
- LinkedHashSet集合特点:
HashSet<String>set=new HashSet<>();//无序,不允许重复
set.add("www");
set.add("abc");
set.add("abc");
set.add("itcase");
System.out.println("HashSet集合:"+set);
LinkedHashSet<String>linked=new LinkedHashSet<>();//有序,不允许重复
linked.add("www");
linked.add("abc");
linked.add("abc");
linked.add("itcase");
System.out.println("LinkedHashSet:"+linked);
可变参数*(JDK1.5之后出现的新特性)
- 使用前提:
- 当方法参数列表的数据类型(此处的数据类型可以是Object)已经确定,但参数个数不确定,就可以使用可变参数
- 使用格式:
- 修饰符 返回值类型 方法名(数据类型 …变量名){}
- 可变参数的原理:
- 可变参数底层就是一个数组,数据传递参数个数不同,会创建不同长度的数组,来储存这些参数
- 传递参数的个数可以是0个(不传递),也可以是多个
- 注意事项:
- 1.一个方法只能有一个可变参数
- 2.如果方法的参数有多个,那么可变参数必须卸下参数的末尾
/**
* @author yolo
* @date 2019/10/12-19:51
*/
public class Demo01VarArgs {
/*
定义一个方法,计算若干0(~n)个整数的和
已知:加u四年整数的和,数据类型已经确定int
但参数的个数不确定,就可以使用可变参数
add3();就会创建一个长度为0的数组,new int[0]
add3(10);就会创建一个长度为1的数组,new int[1]
add3(10,20);就会创建一个长度为2的数组,new int[2]
...
*/
public static int add(int...arr){//可变参数底层就是一个数组,arr是所创建数组的地址
//定义初始化变量
int sum=0;
//遍历数组,获取元素
for (int i : arr) {
sum+=i;
}
return sum;
}
//参数类型为Object的可变参数
public static void method(Object o){}
public static void main(String[] args) {
int i= add(10,20,30,40,50,60,70,80);
System.out.println(i);
}
}