一、HashSet
1、HashSet简单介绍
说到HsahSet就要先说Set接口
Set 接口和List接口一样,同样继承自Collection接口,它与Collection接口中的方法基本一致,并没有对 Collection 接口进行功能上的扩充,只是比Collection接口更加严格。与List 接口不同的是,Set接口中的元素无序,并且都会以某种规则保证存入的元素不出现重复。
Set接口主要有两个实现类,分别是 HashSet和TreeSet。其中,HashSet是根据对象的哈希值来确定元素在集合中的存储的位置,因此具有良好的存取和查找性能。TreeSer则是以二叉树的方式来存储元素,它可以实现对集合中的元素进行排序。
HashSet
HashSet是 Set接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的。当向 HashSet集合中添加一个元素时,首先会调用该元素的hashCode()方法来确定元素的存储位置,然后再调用元素对象的equals()方法来确保该位置没有重复元素
2、HashSet的常用方法
常用方法代码演示:
import java.util.HashSet; import java.util.Iterator; public class Main { public static void main(String[] args) { //使用HashSet集合时先要指定泛型中具体的包装类 HashSet<Integer> hashSet=new HashSet<>(); //向hashSet中添加元素 add() hashSet.add(12); hashSet.add(34); hashSet.add(56); //判断hashSet中是否有12和89两个元素 contains() System.out.println(hashSet.contains(12)); //true System.out.println(hashSet.contains(89)); //false //hashSet中元素的个数 size() System.out.println(hashSet.size()); //3 //Iterator迭代器遍历集合 Iterator<Integer> iterator=hashSet.iterator(); while (iterator.hasNext()){ Integer i=iterator.next(); System.out.println(i); //输出顺序与添加顺序不同 //System.out.println(iterator.next()); } //foreach遍历集合 hashSet.forEach(o-> System.out.println(o)); //输出顺序与添加顺序不同 //hashSet.forEach(System.out::println); //删除hashSet中的某个元素 remove() System.out.println(hashSet.remove(12)); //true 删除成功返回true System.out.println(hashSet.remove(89)); //false 删除失败返回false System.out.println(hashSet.size()); //2 //克隆Hashset实例的浅层副本:元素本身不被克隆。 hashSet.add(12); Object clone=hashSet.clone(); System.out.println(clone); //输出格式为[元素1,元素2] 输出顺序与添加顺序不同 //删除前 判断hashSet是否为空 System.out.println(hashSet.isEmpty()); //false //清空hashSet中的所以元素 hashSet.clear(); //删除后 判断hashSet是否为空 System.out.println(hashSet.isEmpty()); //true } }
3、HashSet保证元素不重复的原理
HashSet集合之所以能确保不出现重复的元素,是因为它在存入元素时做了很多工作。当调用 HashSet集合的add()方法存入元素时,首先调用当前存入元素的hashCode()方法获得对象的哈希值,然后根据对象的哈希值计算出一个存储位置;如果该位置上没有元素则直接将元素存入;如果该位置上有元素存在,则会调用equals()方法让当前存入的元素次和该位置上的元素进行比较。如果返回的结果为false就将该元素存入集合;返回的结果为true则说明有重复元素,就不添加到其中。若想保证输入元素与输出元素顺序保存一致,可以使用LinkedHashSet集合(与HashSet相比,使用区别并不大)
二、HashMap
1、HashMap简单介绍
HashMap集合是 Map接口的一个实现类,它用于存储键值映射关系,该集合的键和值允许为空,但键不能重复且集合中的元素是无序的。HashMap底层是由哈希表结构组成的,其实就是“数组+链表”的组合体,数组是HashMap的主体结构,链表则主要是为了解决哈希值冲突而存在的分支结构。正因为这样特殊的存储结构,HashMap集合对于元素的增、删、改、查操作表现出的效率都比较高。
水平方向以数组结构为主体并在竖直方向以链表结构进行结合的就是 HashMap中的哈希表结构。在哈希表结构中,水平方向数组的长度称为HashMap集合的容量(capacity),竖直方向每个元素位置对应的链表结构称为一个桶(bucket),每个桶的位置在集合中都有对应的桶值,用于快速定位集合元素添加、查找时的位置。
HashMap 几乎等同于HashTable ,但是因为HashTable使用同步锁所以线程安全;
2、HashMet的常用方法
常用方法代码演示:
import java.util.*; public class Main { public static void main(String[] args) { HashMap<Integer, String> hashMap=new HashMap<>(); //1、向hashMap中添加元素 hashMap.put(1,"cat"); hashMap.put(2,"tom"); hashMap.put(3,"house"); hashMap.put(4,"bord"); //2、查看键对象是否存在 System.out.println(hashMap.containsKey(1)); //true //3、查看是否有相应键与该值对应 System.out.println(hashMap.containsValue("cat")); //true //4、获取集合中的 键对象和值对象 集合 System.out.println(hashMap.keySet()); //[1, 2, 3, 4] System.out.println(hashMap.values()); //[cat, tom, house, bord] //5、替换指定键对象映射的值 hashMap.replace(1,"cat1"); System.out.println(hashMap); //{1=cat1, 2=tom, 3=house, 4=bord} //6、删除指定键对象映射的键值对元素 System.out.println(hashMap.size()); //4 hashMap.remove(4); System.out.println(hashMap); //{1=cat1, 2=tom, 3=house} System.out.println(hashMap.size()); //3 //7、hashMap实例的浅拷贝 Object map=hashMap.clone(); System.out.println(map); //{1=cat1, 2=tom, 3=house} //8、查看该key是否存在,若存在返回其value,否则返回defaultValue System.out.println(hashMap.getOrDefault(3,"No")); //house System.out.println(hashMap.getOrDefault(4,"No")); //No //9、遍历hashMap // 1)forEach遍历 hashMap.forEach((key,value)-> System.out.println(key+" "+value)); //1 cat1 2 tom 3 house //2)Iterator迭代器遍历集合 Set<Integer> keySet=hashMap.keySet(); Iterator<Integer> iterator=keySet.iterator(); while (iterator.hasNext()){ Object key=iterator.next(); Object value=hashMap.get(key); System.out.println(key+" "+value); //1 cat1 2 tom 3 house } /*简单for循环也可以 for (Object key : keySet) { Object value = hashMap.get(key); System.out.println(key + " " + value); }*/ //8、删除hashMap中的所有映射关系,并判断是否为空 System.out.println(hashMap.isEmpty()); //false hashMap.clear(); System.out.println(hashMap.isEmpty()); //false } }
3、使用LinkedHashMap集合保证元素添加顺序
import java.util.*; public class Main { public static void main(String[] args) { HashMap<Integer, String> hashMap=new HashMap<>(); //1、向hashMap中添加元素 hashMap.put(2,"tom"); hashMap.put(1,"cat"); hashMap.put(4,"bord"); hashMap.put(3,"house"); System.out.println("hashmap:"); hashMap.forEach((key,value)-> System.out.println(key+":"+value)); LinkedHashMap<Integer,String> linkedHashMap=new LinkedHashMap<>(); linkedHashMap.put(2,"tom"); linkedHashMap.put(1,"cat"); linkedHashMap.put(4,"bord"); linkedHashMap.put(3,"house"); System.out.println("linkedHashMap:"); linkedHashMap.forEach((key,value)-> System.out.println(key+":"+value)); } }
三、HashSet和HashMap的区别和联系
1、区别
HashSel | HashMap |
HashSet实现了Set接口 | HashMap实现了Map接口 |
HashSet仅仅存储对象 | HashMap储存键值对 |
使用add()方法将元素放入set中 | 使用put()方法将元素放入map中 |
HashSct使用成员对象来计算hashcodc值,对于两个对象来说hashCode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false,即添加该元素 | HashMap中使用键(key)对象来计算 hashCode |
HashSet较HashMap来说比较慢 | HashMap比较快,因为是使用唯一的键 来获取对象 |
HashSet允许具有单个空值。 | HashMap允许单个null键和任意数量的空值。 |
HashSet不允许重复元素,这意味着您无法在HashSet中存储重复值。 | HashMap不允许有重复键,但它可以有重复值 |
2、联系
对于HashSet而言,它是基于HashMap实现的,HashSet底层使用HashMap来保存所有元素,更确切的说,HashSet中的元素,只是存放在了底层HashMap的key上, 而value使用一个static final的Object对象标识。