***\*Set子接口\**** 之***\*HashSet\****
*Set子接口*
特点:无序、无下标、元素不可以重复。
方法:全部继承自Collection中的方法
这个借口提供的方法全部继承自Collection接口中,没有新定义其他的方法
*Set实现类*
HashSet 重点(存储过程)
基于hashcode计算元素存放位置。
当存入元素的哈希码相同时(表示存放的位置是相同的),会调用equals进行确认,如果结果为true,则拒绝后者存入。如果不相等则会以链表的形式连接。
TreeSet:存储结构是红黑树,二叉查找树
基于排列顺序实现元素不重复。
实现了SortedSet接口,对集合元素自动排序。
元素对象的类型必须实现Comparable接口,指定排序规则。
通过CompareTo方法确定是否为重复元素。
*HashSet*
代码练习
package com.genericlist;
import java.util.HashSet;
import java.util.Iterator;
import java.util.ListIterator;
/**
* 测试Set接口的使用
* 特点:1.无序,没有下标 2.不能重复
*/
public class SetDemo01 {
public static void main(String[] args) {
HashSet<String> set = new HashSet<String>();
//1.添加数据
set.add("apple");
set.add("bananer");
set.add("Durian");//表示榴莲
set.add("apple");
System.out.println("集合大小====" + set.size());
System.out.println("集合遍历====" + set);//默认重写的toString方法
System.out.println("=========3.1使用增强for==========");
for (Object o : set) {
String col1 = (String) o;
System.out.println(col1);
}
//迭代器是专门用来遍历集合的一种方式
System.out.println("=========3.2使用iterator迭代器==========");
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
String col2 = (String) iterator.next();
System.out.println(col2);
//java.util.ConcurrentModificationException 并发修改异常,也就是说,再遍历集合的时候,是不能够删除集合中的元素的。
//set.remove(col2);
//要想在遍历的时候删除集合中的元素可以使用迭代器提供的删除方法进行删除
// iterator.remove();
}
// System.out.println("集合大小===="+set.size());s
// System.out.println("=========3.3使用普通for循环进行遍历==========");
//set集合是不能够使用普通的for循环进行遍历的
// for (int i = 0; i <set.size() ; i++) {
// System.out.println(set.get(i));
// } 注意:set 集合是不能够使用下标的方式进行遍历的,所以下面两种方式也是不可以的
//使用列表迭代器,和iterator的区别,listiterator可以向前或者向后遍历,添加、删除、修改元素。
// System.out.println("=========3.4使用列表迭代器从前往后遍历==========");
// ListIterator listIterator = set.listIterator();
// while (listIterator.hasNext()) {
// System.out.println(listIterator.nextIndex()+":"+listIterator.next());
// }
// System.out.println("=========3.4使用列表迭代器从后往前遍历==========");
// while (listIterator.hasPrevious()) {
// System.out.println(listIterator.previousIndex()+":"+listIterator.previous());
// }
// * 4.判断
System.out.println(set.contains("apple"));//判断集合中是否存在该元素
System.out.println(set.isEmpty());//判断集合是否为空
}
}
运行结果:
运行结果:
集合大小====3
集合遍历====[apple, Durian, bananer]
=========3.1使用增强for==========
apple
Durian
bananer
=========3.2使用iterator迭代器==========
apple
Durian
bananer
true
False
*小练习*
package com.genericlist;
import java.util.HashSet;
import java.util.Iterator;
/**
* 测试Set接口的使用
* 特点:1.无序,没有下标 2.不能重复
* 存储结构:哈希表(数组+链表+红黑树)
*/
public class SetDemo02 {
public static void main(String[] args) {
HashSet<String> set = new HashSet<String>();
//1.添加数据
set.add("apple");
set.add("bananer");
set.add("Durian");//表示榴莲
set.add("apple");//set集合是不允许重复的
System.out.println("集合大小===="+set.size());
System.out.println("集合遍历===="+set);//默认重写的toString方法
//2.删除操作
set.remove("apple");
System.out.println("删除之后集合大小===="+set.size());
System.out.println("删除之后集合遍历===="+set);//默认重写的toString方法
// System.out.println("=========3.1使用增强for==========");
// for (Object o : set) {
// String col1=(String) o;
// System.out.println(col1);
// }
// //迭代器是专门用来遍历集合的一种方式
// System.out.println("=========3.2使用iterator迭代器==========");
// Iterator<String> iterator = set.iterator();
// while (iterator.hasNext()){
// String col2 = (String)iterator.next();
// System.out.println(col2);
// //java.util.ConcurrentModificationException 并发修改异常,也就是说,再遍历集合的时候,是不能够删除集合中的元素的。
// //set.remove(col2);
// //要想在遍历的时候删除集合中的元素可以使用迭代器提供的删除方法进行删除
//// iterator.remove();
// }
//// System.out.println("集合大小===="+set.size());s
//// System.out.println("=========3.3使用普通for循环进行遍历==========");
//// for (int i = 0; i <set.size() ; i++) {
//// System.out.println(set.get(i));
//// } 注意:set 集合是不能够使用下标的方式进行遍历的,所以下面两种方式也是不可以的
// //使用列表迭代器,和iterator的区别,listiterator可以向前或者向后遍历,添加、删除、修改元素。
//// System.out.println("=========3.4使用列表迭代器从前往后遍历==========");
//// ListIterator listIterator = set.listIterator();
//// while (listIterator.hasNext()) {
//// System.out.println(listIterator.nextIndex()+":"+listIterator.next());
//// }
//// System.out.println("=========3.4使用列表迭代器从后往前遍历==========");
//// while (listIterator.hasPrevious()) {
//// System.out.println(listIterator.previousIndex()+":"+listIterator.previous());
//// }
//// * 4.判断
// System.out.println(set.contains("apple"));//判断集合中是否存在该元素
// System.out.println(set.isEmpty());//判断集合是否为空
}
}
运行结果:
集合大小====3
集合遍历====[apple, Durian, bananer]
删除之后集合大小====2
删除之后集合遍历====[Durian, bananer]
小练习
package com.genericlist;
import com.sun.org.apache.xpath.internal.operations.Equals;
/**
* 人类
*/
public class Person implements Comparable<Person> {
private String name;
private int age;
public Person() {
}
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 +
'}';
}
/**
* 解释:为什么使用31
* 1.31是一个质数,能够减少散列冲突 2.31能够提高执行效率 31 * i = (i << 5) - i(左边 31*2=62,右边 2*2^5-2=62) - 两边相等
*
* @return
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
//重写hashcode方法进行内存地址的判断
// @Override
// public int hashCode() {
// int n1 = this.name.hashCode();
// int n2 = this.age;
// return n1 + n2;
// }
//必须重写equals方法才能判断添加的对象是否重复
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (obj instanceof Person) {
Person person = (Person) obj;
if (this.name.equals(person.getName()) && this.age == person.getAge()) {
return true;
}
}
return false;
}
/**
* 先按照姓名比较,再按照年龄进行比较,如果姓名相同,则返回年龄
*
* @param o
* @return
*/
public int compareTo(Person o) {
int n1 = this.getName().compareTo(o.getName());
int n2 = this.age - o.getAge();
return n1 == 0 ? n2 : n1;
}
}
package com.genericlist;
import java.util.HashSet;
import java.util.Iterator;
/**
* 测试Set接口的使用
* 特点:1.无序,没有下标 2.不能重复
* 存储结构:哈希表(数组+链表+红黑树)
* 存储过程:(这也是判断元素重复的依据)(1)根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步。
* (2)再执行equals方法,如果equals方法为true,则认为是重复,否则,形成链表。
* 注意:hashcode方法和equals方法必须都同时重写才行,重写其中一个都是不能实现是否为同一个对象的判断逻辑。
* 最后是既有数组又有链表
*/
public class SetDemo03 {
public static void main(String[] args) {
HashSet<Person> setPerson = new HashSet<Person>();
//1.添加数据
Person person01 = new Person("张三", 20);
Person person02 = new Person("李四",21);
Person person03 = new Person("王五",22);
setPerson.add(person01);
setPerson.add(person02);
setPerson.add(person03);
// setPerson.add(person03);//这样添加是添加不进来的
setPerson.add(new Person("王五",22));//这样添加就是能够添加进来的,因为这个对象在堆中的内存地址和person3的内存地址不一样
System.out.println("集合大小===="+setPerson.size());
System.out.println("集合遍历===="+setPerson);//默认重写的toString方法
// //2.删除操作
// setPerson.remove(person01);//
// setPerson.remove(new Person("张三", 20));//这种方法也是能够删除的
// System.out.println("删除之后集合大小===="+setPerson.size());
// System.out.println("删除之后集合遍历===="+setPerson);//默认重写的toString方法
System.out.println("=========3.1使用增强for==========");
for (Object o : setPerson) {
Person col1=(Person) o;
System.out.println(col1);
}
// //迭代器是专门用来遍历集合的一种方式
System.out.println("=========3.2使用iterator迭代器==========");
Iterator<Person> iterator = setPerson.iterator();
while (iterator.hasNext()){
Person col2 = (Person)iterator.next();
System.out.println(col2);
//java.util.ConcurrentModificationException 并发修改异常,也就是说,再遍历集合的时候,是不能够删除集合中的元素的。
//set.remove(col2);
//要想在遍历的时候删除集合中的元素可以使用迭代器提供的删除方法进行删除
// iterator.remove();
}
//// * 4.判断
System.out.println(setPerson.contains(new Person("张三", 20)));//判断集合中是否存在该元素
System.out.println(setPerson.contains(person01));//判断集合中是否存在该元素
System.out.println(setPerson.isEmpty());//判断集合是否为空
}
}
运行结果:
集合大小====3
集合遍历====[Person{name='李四', age=21}, Person{name='王五', age=22}, Person{name='张三', age=20}]
=========3.1使用增强for==========
Person{name='李四', age=21}
Person{name='王五', age=22}
Person{name='张三', age=20}
=========3.2使用iterator迭代器==========
Person{name='李四', age=21}
Person{name='王五', age=22}
Person{name='张三', age=20}
true
true
false