hahmap和set使用与注意事项!

map和set

哈希表(hashMap)和 集合 (Set)是数据结构中比较常用的一部分,他们的特性通常可以解决很多问题,这两个数据结构是同根生,存储数据的方式也很特别。hashmap相当于一个地图,存储数据是按照键值对的方式来存储的,就等于一种类对象的数据模式。Set是一种集合,存储方式与数组差不多。不过虽然这两种数据结构与其他数据有些相同之处,不过他们最大的区别就是,set中不会存储两个相同的值,存储在set中的值都是唯一的。同样的,hashmap中的键也是唯一的。利用这两个数据的特性解决一些问题是不是会方便许多。

Set的两种常用形态

Set是一个Java集合框架的一个接口,存储的元素都是唯一的。因为是接口,所有只能使用接口实现类来构造:
在这里插入图片描述

常见的有三种,常用的只有两种:HashSet,TreeSet,那么这两个分别有什么区别呢?

特性比较HashSetTreeSet
内部实现使用红黑树实现使用哈希表实现
有序性有序无序
查找删除元素时性能时间复杂度为常数时间复杂度为O(log2)
对元素相等时的判断使用equals使用比较器或者comparaTo方法
数据大时优先选择不推荐

先来了解一下如何构造:

set和map后的<>中可以添加基本数据类型和引用类型

Set<Integer> set = new HashSet<>();
HashSet<Integer> hashSet = new HashSet<>();
TreeSet<Integer> treeSet = new TreeSet<>();

学习完构造方法,那我们来了解一些方法,如何快速上手:

在这里插入图片描述

leetcode:宝石与石头

可以拿这个题练习一下使用。

这里我使用了Set保存’宝石‘,然后去石头中进行对比,得到宝石数量,返回即可。利用了set中的元素唯一性和判断元素存在集合的方法。感兴趣的小伙伴可以多多练习。

class Solution {
    public int numJewelsInStones(String jewels, String stones) {
        Set<Character> set = new HashSet<>();
        for (char ch:jewels.toCharArray()) {
            set.add(ch);
        }
        int ret = 0;
        for (char ch:stones.toCharArray()) {
            if(set.contains(ch)){
             ret++;   
            }
        }
        return ret;
    }
}

Map的两种常用形态

与前者一样,map也是Java的数据框架接口类,因为它独特的存储方式,备受喜爱,在排除元素或者统计元素个数时使用十分方便,因为HaspMap查找一个数据的时间复杂度是一个常数项,也就是O(1),几乎达到了最快速度。查找元素如此高效与它底层结构脱不了干系!

特性HashMapTreeMap
底层数据结构链表加数组或红黑树红黑树
排序无序有序,按升序排序
查找元素删除元素效率高效,时间复杂度为O(1)时间复杂度为O(log2)
使用空间时内存相对于TreeMap少使用内存多一些,需要维护树

如何构造一个哈希表:

//T是泛型
HashMap<T,T> hashMap = new HashMap<>();
TreeMap<T,T> treeMap = new TreeMap<>();

map基本方法:

在这里插入图片描述

使用map存储普通数据类型:

public static void main(String[] args) {
        //存储普通数据类型
        HashMap<String,Integer> hashMap = new HashMap<>();
        TreeMap<String,Integer> treeMap = new TreeMap<>();
        //添加普通数据类型
        hashMap.put("aaa",1);
        hashMap.put("bbb",2);
        treeMap.put("aaa",1);
        treeMap.put("bbb",2);
        System.out.println("hashmap:"+hashMap);
        System.out.println("treeMap:"+treeMap);
}

在这里插入图片描述

可以看到map的存储方式是键值对,map存储数据有一个非常需要注意的地方!map的是唯一的,意味着如果在同一个map中存储两个键相同的数据,这表明后一个值会将前一个值进行替换!

如下:

public static void main(String[] args) {
        //存储普通数据类型
        HashMap<String,Integer> hashMap = new HashMap<>();
        hashMap.put("aaa",1);
        hashMap.put("aaa",2);
        System.out.println("hashmap:"+hashMap);
}

在这里插入图片描述

map中不仅可以存储普通数据类型,还可以使用类对象作为键:

public static void main(String[] args) {
        HashMap<Student,Integer> hashMap = new HashMap<>();
        TreeMap<Student,Integer> treeMap = new TreeMap<>();
        //HashMap的打印
        hashMap.put(new Student(),10);
        hashMap.put(new Student(),20);
        System.out.println(hashMap);
        //TreeMap的打印
        treeMap.put(new Student(),10);
        treeMap.put(new Student(),20);
        System.out.println(treeMap);
}

在这里插入图片描述

这个案例可以清楚的发现这两者之间的不同之处,当hashmap和treemap存储的数据相同时,hashmap可以正常存储,而treemap在存储时会发生错误,观察错误是说明应该添加一个comparable(比较器)这个说明了在hashmap中数据是无序存在的,而在treemap中是有序存在的,当存储一个数据时,treemap必须要知道数据排列的方式。

存储数据时treemaphashmap中键和值的区别(可以为null吗?)!

public static void main(String[] args) {
        HashMap<Integer,Integer> hashMap = new HashMap<>();
        TreeMap<Integer,Integer> treeMap = new TreeMap<>();
        //HashMap的打印
        hashMap.put(null,10);//键为null,值不为空
        System.out.println(hashMap);
        //TreeMap的打印
        treeMap.put(null,10);
        System.out.println(treeMap);
}

在这里插入图片描述

可以看到treemap抛出空指针异常,说明不能以null作为treemap的键。

public static void main(String[] args) {
        HashMap<Integer,Integer> hashMap = new HashMap<>();
        TreeMap<Integer,Integer> treeMap = new TreeMap<>();
        //HashMap的打印
        hashMap.put(2,null);
        System.out.println(hashMap);
        //TreeMap的打印
        treeMap.put(2,null);
        System.out.println(treeMap);
}

在这里插入图片描述

当使用null作为值时,可以看到打印结果,并没有异常抛出,说明null值是可以作为值存在于map中。

练习:字符串中的第一个唯一字符

public int firstUniqChar(String s) {
        int ret = -1;
        //建立一个哈希表存储字符和记录字符个数
        HashMap<Character,Integer> hashMap = new HashMap<>();
        for (int i = 0; i <s.length() ; i++) {
            hashMap.put(s.charAt(i),hashMap.getOrDefault(s.charAt(i),0)+1);
        }
        for (int i = 0; i <s.length() ; i++) {
            //从前往后遍历,找到第一个符合条件的字符,退出循环
            if(hashMap.get(s.charAt(i))==1){
                ret = i;
                break;
            }
        }
        return ret;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值