Set集合
- 特点:无序、无下标、元素不可重复
- 方法:全部继承自Collection中的方法
- 增、删、遍历、判断与collection一致
Set实现类
/**
* 测试Set接口的使用
* 特点:1.无序、没下标 2.不能重复
* @author wgy
* */
public class Demo1 {
public static void main(String[] args) {
//1添加数据
Set<String> set = new HashSet();
set.add("小米");
set.add("华为");
set.add("OPPO");
//2删除数据
set.remove("OPPO");
//3遍历【重点】
//3.1怎强for循环
for (String string : set) { //增强for循环的类型如果设为String,上面new的时候也就要加上泛型<String>
System.out.println(string);
}
//3.2迭代器
Iterator<String> it = set.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
}
HashSet【重点】
-
存储结构:哈希表(数组+ 链表+ 红黑树)
-
存储过程(重复依据):
- 基于HashCode计算元素存放位置,如果位置为空,直接保存。若不为空,进行第二步
- 在执行equals方法,如果equals结果为true,则认为是重复,否则,形成链表
-
特点:
- 基于HashCode计算元素存放位置
- 利用31这个质数,减少散列冲突(重写hashCode时,系统自动生成的一种方法。现在的版本不会出现这个方法了)
- 31提高执行效率
31 * i = (i<<5) - i
转为移位操作
- 31提高执行效率
- 当存入元素的哈希码相同时,会调用equals进行确认,如果结果为true则拒绝后者存入
- 利用31这个质数,减少散列冲突(重写hashCode时,系统自动生成的一种方法。现在的版本不会出现这个方法了)
- 基于HashCode计算元素存放位置
新建集合 HashSet<String> hashSet = new HashSet<String>();
添加元素 hashSet.add( );
删除元素 hashSet.remove( );
遍历操作
-
增强for
for( type type : hashSet)
-
迭代器
Iterator<String> it = hashSet.iterator( );
判断 hashSet.contains( );
hashSet.isEmpty();
练习:
public class Demo3 {
public static void main(String[] args) {
HashSet<Person> persons = new HashSet<>();
//1添加数据
Person p1 = new Person("刘德华",10);
Person p2 = new Person("周杰伦",43);
Person p3 = new Person("梁朝伟",60);
persons.add(p1);
persons.add(p2);
persons.add(p3);
//persons.add(p3); //重复
persons.add(new Person("梁朝伟",60));
System.out.println("元素个数:"+ persons.size());
System.out.println(persons.toString());
//删除操作
// persons.remove(p1);
persons.remove(new Person("刘德华",10));//重写hashCode和equals之后,判断的依据就是hashCode和equals,先根据hashCode判断在哪个位置,再比equals。不重写的话,就不能这样删除。
System.out.println("删除之后元素个数:"+persons.size());
//3遍历
//3.1增强for
for (Person p: persons) {
System.out.println(p);
}
//3.2迭代器
Iterator<Person> per = persons.iterator();
while (per.hasNext()){
System.out.println(per.next());
}
//4判断
System.out.println(persons.contains(p2));
System.out.println(persons.contains(new Person("梁朝伟",60)));
System.out.println(persons.isEmpty());
}
Person方法(重写hashCode和equals)
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public int hashCode(){ //重写hashCode
int n1 = this.name.hashCode();
int n2 = this.age;
return n1 + n2;
}
public boolean equals(Object obj) { //重写equals
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
Person p = null;
if (obj instanceof Person) {
p = (Person) obj;
}
if (this.name.equals(p.getName()) && this.age == p.getAge()) {
return true;
}
return false;
}
}
TreeSet
- 基于排列顺序实现元素不重复
- 实现了SortedSet接口,对集合元素自动排序。
- 元素对象的类型必须实现Comparable接口,指定排序规则。
- 通过ComareTo方法确定是否为重复元素。
存储结构:红黑树
创建集合 TreeSet<String> treeSet = new TreeSet<>()
添加元素 treeSet.add();
删除元素 treeSet.remove();
遍历 1. 增强for 2. 迭代器
判断 treeSet.contains();
重写compareTo:
public class Person implements Comparable<Person>{
//先按姓名比,再按年龄比
public int compareTo(Person o ) {
int n1 = this.getName().compareTo(o.getName());//那当前对象的名字和传过来的 o 进行比较
int n2 = this.age-o.getAge();//如果年龄一样就是0
return n1==0?n2:n1;
}
}
练习:
/***
* 使用TreeSet保存数据
* 存储结构:红黑树
* 要求:元素必须实现Comparable接口,compareTo()方法返回值为0,认为是重复元素
*/
public class Demo5 {
public static void main(String[] args) {
//创建集合
TreeSet<Person> persons = new TreeSet<>(); //需要告诉对线该怎么比较
Person p1 = new Person("张旭",32);
Person p2 = new Person("王喜",43);
Person p3 = new Person("张德江",76);
Person p4 = new Person("王喜",76);
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
System.out.println("元素个数:" + persons.size());
System.out.println(persons.toString());
//2删除
persons.remove(p1);
persons.remove(new Person("王喜",76));
System.out.println(persons.size());
//3遍历
//3.1使用增强for循环
for (Person person: persons) {
System.out.println(person);
}
//3.2迭代器
Iterator it = persons.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//4判断
System.out.println(persons.contains(p1));
System.out.println(persons.contains(new Person("王喜",43)));
}
}
补充:TreeSet集合的使用
Comparator 实现定制比较(比较器)
Comparable 可比较的
// 在主函数内重写
@override
public int compare(Person o1, Person o2){
int n1 = o1.getAge()-o2.getAge();
int n2 = o1.getName().comareTo(o2.getName());
return n1 == 0 ? n2 : n1;
}
练习:
/**
* TreeSet集合的使用
* Comparator:实现定制比较(比较器)
* Comparable:可比较的
* */
public class Demo6 {
public static void main(String[] args) {
//创建集合,并指定比较规则
TreeSet<Person> persons = new TreeSet<>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
int n1 = o1.getAge() - o2.getAge();
int n2 = o1.getName().compareTo(o2.getName());
return n1 == 0 ? n2:n1;
}
});
Person p1 = new Person("张旭",32);
Person p2 = new Person("王喜",43);
Person p3 = new Person("张德江",76);
Person p4 = new Person("王喜",76);
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
System.out.println(persons.size());
System.out.println(persons.toString());
}
}
练习: – 定制比较,先比较字符串长度,再比较字符
public class Demo7 {
public static void main(String[] args) {
TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int n1 = o1.length() - o2.length();
int n2 = o1.compareTo(o2);
return n1 == 0 ? n2:n1;
}
});
//添加数据
treeSet.add("shanghai");
treeSet.add("hangzhou");
treeSet.add("taiwan");
treeSet.add("xian");
treeSet.add("xiamen");
System.out.println("元素的个数是:" + treeSet.size());
System.out.println(treeSet.toString());
}
}