18、Hashset Hashmap

image-20210720204712106.

1、HashSet

1、Set是无序、不包含重复元素、可以存放null值的Collection,

2、当Set的泛型引用自定义的类时,自定类中需要重写toString()、hashcode()、equals()三个方法才能表现set不可重复性的特性

package cn.tedu.set;
/*本类用于测试set接口*/

import java.util.HashSet;
import java.util.Set;

public class TestSet {
    public static void main(String[] args) {
        Set<String> set=new HashSet<>();
        /*无序、不能重复、可以存放null值*/
        set.add("牛气冲天");
        set.add("虎虎生威");
        set.add("虎虎生威");
        set.add(null);
        set.add("null");
        System.out.println(set);


        System.out.println("===================");
        /*Set集合如果要定义自己写的泛型类,那么定义的类需要重写toString、hashCode()、equals才能实现set的不重复特性*/
        Set<Studnet>  set2=new HashSet<>();
        Studnet s1 = new Studnet("张三", 3);
        Studnet s2 = new Studnet("李四", 4);
        Studnet s3 = new Studnet("李四", 4);
        set2.add(s1);
        set2.add(s2);
        set2.add(s3);
        System.out.println(set2);
    }
}

2、HashMap

2.1、特点

1、HashMap底层结构:数组+链表(链表长度小于6时)

​ 数组+红黑树(链表的长度大于8时)

2、HashMap实际上是存放一个个Entry(k,v);

3、Map的初始容量是16,默认的加载因子是0.75f(当存放16*0.75个数组时就会扩容),约等于2倍扩容注意会发生rehash

4、map中当键key相同时value值会覆盖之前的;

5、当存放数据时,会根据hash算法来计算数据的存放位置,算法:hash(key)%n , n就是数组的长度,其实也就是集合的容量

image-20210720202322049

2.2、常用方法
package cn.tedu.map;
/*本类用于测试map接口*/

import java.util.*;

public class TestMap {
    public static void main(String[] args) {
        /*1.Map中的数据要符合映射规则,一定注意要同时指定K和V的数据类型*/
        Map<Integer,String>  map=new HashMap<>();
        /*2.map集合存放数据的方法时put(),需要同时赋值k和v*/
        map.put(9527,"白骨精");
        map.put(9528,"黑熊精");
        map.put(9529,"鲤鱼精");
        map.put(9530,"黄毛怪");
        map.put(9531,"黑熊精");
        map.put(9527,"爱莎公主");
        /*1、map中存放的都是无序的数据
          2、map中的value值可以重复
          3、map中的key值不能重复,不然之前的value值会被覆盖*/
        System.out.println(map);

//        map.clear();
        System.out.println(map.hashCode());
        System.out.println(map.equals("黄毛怪"));
        System.out.println(map.isEmpty());
        System.out.println(map.size());

        System.out.println(map.containsKey(9527));//判断map集合中是否存在指定的键key
        System.out.println(map.containsValue("白骨精"));//判断map集合中是否存在指定的值value
        System.out.println(map.get(9527));//根据key获取对应的value值
        System.out.println(map.remove(9529));//删除此key值对应的键值对
        System.out.println(map.containsKey(9529));

        Collection<String> values = map.values();//把map中的值取出来放在一个Collection集合中
        System.out.println(values);
        

    }
}
2.3、两种迭代方式

image-20210720204944405.

map集合没有迭代器,需要借助Set里的iterator迭代器

方式一:Set keySet = map.keySet();

方式二:Set<Map.Entry<Integer, String>> entries = map.entrySet();

package cn.tedu.map;

import java.util.*;

public class test {
    public static void main(String[] args) {
        Map<Integer,String> map=new HashMap<>();
        map.put(9527,"白骨精");
        map.put(9528,"黑熊精");
        map.put(9529,"鲤鱼精");
        map.put(9530,"黄毛怪");
        map.put(9531,"黑熊精");
        map.put(9527,"爱莎公主");

        //map集合的迭代方式  map本身没有迭代器,需要先转换为set集合
        /*方式一(keySet()):Set<key>把map的所有key值存到set集合中*/
        Set<Integer> keySet = map.keySet();
        Iterator<Integer> it = keySet.iterator();
        while (it.hasNext()){
            Integer key = it.next();
            String value = map.get(key);
            System.out.println("{"+key+","+value+"}");
        }
      

        /*方式二(entrySet):把map中的一个键值对key&value作为一个Entry<k,v>整体放入set
         * 一对K,V就是一个Entry*/
        Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
        Iterator<Map.Entry<Integer, String>> iterator = entrySet.iterator();
        while (iterator.hasNext()){
            Map.Entry<Integer, String> entry = iterator.next();
            Integer key = entry.getKey();
            String value = entry.getValue();
            System.out.println("{"+key+","+value+"}");
        }
    }
}

2.4、利用HashMap统计字符串中字符

注意:引用类型的初始值都是null哦!

package cn.tedu.map;
/*本类用于字符串中字符个数统计案例*/

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class TestMap2 {
    public static void main(String[] args) {
        System.out.println("请您输入域要统计的字符串:");
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        /*统计的是每个字母出现的次数,单个字符是char,对应的包装类是Character
        * Integer统计的是这个字母出现的次数,可以重复,所以放在value位置*/
        Map<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < input.length(); i++) {
            char key = input.charAt(i);//获取字符串指定下标处的值
            Integer value = map.get(key);
            if (value==null){
                map.put(key,1);
            }else {
                map.put(key,value+1);
            }
        }
        System.out.println(map);
    }
}

3、拓展

HashMap扩容
成长因子:
static final float DEFAULT_LOAD_FACTOR = 0.75f;
前面的讲述已经发现,当你空间只有仅仅为10的时候是很容易造成2个对象的hashcode 所对应的地址是一个位置的情况。这样就造成 2个 对象会形成散列桶(链表)。这时就有一个加载因子的参数,值默认为0.75 ,如果你hashmap的 空间有 100那么当你插入了75个元素的时候 hashmap就需要扩容了,不然的话会形成很长的散列桶结构,对于查询和插入都会增加时间,因为它要一个一个的equals比较。但又不能让加载因子很小,如0.01,这样显然是不合适的,频繁扩容会大大消耗你的内存。这时就存在着一个平衡,jdk中默认是0.75,当然负载因子可以根据自己的实际情况进行调整。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值