HashSet集合保证元素唯一
提问:传统方式保证集合或者数组元素唯一的方法是什么?
回答:通过重写equals()方法,及存一个元素,让它与之前的元素做比较,相同就不存,不相同就存储,但是这样效率简直太低了,如果集合(数组)中有1000个元素,当存入第1001个元素就要分别与之前的元素作比较。
追问:那有什么办法吗?
回答:你仿佛忘记了Set集合它的一个子类HashSet类,它底层数据结构是哈希表和链表,哈希表可以保证你存入元素的唯一性。
public class SetDemo {
public static void main(String[] args) {
HashSet<Integer> set = new HashSet<>();
set.add(1);
set.add(1);
set.add(2);
set.add(3);
set.add(5);
set.add(5);
for (Integer integer : set) {
System.out.print(integer+" ");
}
}
}
运行结果
1 2 3 5 //重复元素没有存入集合
HashSet集合究竟如何保证元素唯一的呢?
前提也是关键所在,存入元素必须重写hashCode()和equals()方法
当元素存入HashSet集合中时,HashSet会调用该对象元素的hashCode()方法获取该对象的hashCode值,然后通过获得哈希值将该元素存入对应位置的上,这样就保证了高效,不用每次存入都进行大量的比较,但是前提是必须重写hashCode()方法,但是难免会出现不同的元素哈希值却相同,所以当哈希值相同的时候会通过equals()方法比较,如果两个对象的哈希值相同,equals()方法的返回值也相同,就不会存入集合保证元素唯一性,如果哈希值相同,equals()方法比较结果不相同,则表明不是相同元素,存入对应位置(存入该哈希表对应位置,如果该位置还有元素则以链表的形式存入)。
TreeSet实现排序的两种方式
1、自然排序
需要排序的对象必须实现Comparable接口,实现CompareTo方法
提问:如果是String类型或者基本包装类型,如何实现Comparable接口?
回答:这些类的底层都已经实现该接口,所以直接可以用自然排序
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Integer> set = new TreeSet<>();
set.add(3);
set.add(3);
set.add(2);
set.add(1);
set.add(5);
for (Integer integer : set) {
System.out.print(integer+" ");
}
}
}
执行结果 1 2 3 5
提问:那如果需要排序的自定义类型呢?比如我要按照学生年龄进行排序呢?
//实现Comparable接口
public class Student implements Comparable<Student>{
private String name;
private int age;
public Student() {
}
public Student(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;
}
//重写compareTo()方法
@Override
public int compareTo(Student s) {
int num=this.age-s.getAge();
int num2=num==0?this.name.compareTo(s.getName()):num;
return num2;
}
class TreeSetTest {
public static void main(String[] args) {
//无参构造,自然排序
TreeSet<Student> set = new TreeSet<>();
set.add(new Student("张三",18));
set.add(new Student("李四",19));
for (Student student : set) {
System.out.println(student.getName()+" "+student.getAge());
}
}
}
运行结果
张三 18
李四 19
2、比较器排序
//未实现Comparable接口
public class Student{
private String name;
private int age;
public Student() {
}
public Student(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;
}
}
class TreeSetTest {
public static void main(String[] args) {
//有参构造传入一个比较器对象
TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num=s1.getAge()-s2.getAge();
int num2=num==0?s1.getName().compareTo(s2.getName()):num;
return num2;
}
});
set.add(new Student("张三",18));
set.add(new Student("李四",19));
for (Student student : set) {
System.out.println(student.getName()+" "+student.getAge());
}
}
}
HashMap集合的两种遍历方式
1、获取所有键存入Set集合,遍历取出键,通过get()方法键找值
public class HasMapDemo {
public static void main(String[] args) {
TreeMap<Integer, String> map = new TreeMap<>();
map.put(1,"a");
map.put(2,"b");
map.put(3,"c");
map.put(4,"d");
map.put(4,"e");
//键值对对象
Set<Integer> set = map.keySet();
for (Integer integer : set) {
String s = map.get(integer);
System.out.println("key="+integer+" value="+s);
}
}
}
运行结果
key=1 value=a
key=2 value=b
key=3 value=c
key=4 value=e
2、获取键值对集合(entry集合),遍历键值对集合,通过Entry提供的getKey()和getValue()获取键和值
public class HasMapDemo2 {
public static void main(String[] args) {
TreeMap<Integer, String> map = new TreeMap<>();
map.put(1,"a");
map.put(2,"b");
map.put(3,"c");
map.put(4,"d");
map.put(4,"e");
//Entry
Set<Map.Entry<Integer, String>> entries = map.entrySet();
for (Map.Entry<Integer, String> entry : entries) {
Integer key = entry.getKey();
String value = entry.getValue();
System.out.println("key="+key+" value="+value);
}
}
}