二十三、JAVA中的Set和Map

1. Set接口

1.1 概述

一个不包含重复元素的 collection。

数据无序(因为set集合没有下标)。

由于集合中的元素不可以重复。常用于给数据去重。

1.2 特点

  • HashSet:底层是哈希表,包装了HashMap,相当于向HashSet中存入数据时,会把数据作为K,存入内部的HashMap中。当然K仍然不许重复。

  • TreeSet:底层就是TreeMap,也是红黑树的形式,便于查找数据。

  • HashMap实现中,当哈希值相同的对象,会在同一个hash值的位置存储不同属性的数据。

1.3 常用方法

boolean add(E e):添加元素。

boolean addAll(Collection  c):把小集合添加到大集合中 。

boolean contains(Object o) : 如果此 collection 包含指定的元素,则返回 trueboolean isEmpty() :如果此 collection 没有元素,则返回 trueIterator<E> iterator():返回在此 collection 的元素上进行迭代的迭代器。

boolean remove(Object o) :从此 collection 中移除指定元素的单个实例。

int size() :返回此 collection 中的元素数。

Objec[] toArray():返回对象数组

1.4 案例 测试常用方法

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
 
public class TestMap {
       public static void main(String[] args) {
              Set set = new HashSet ();
              set.add("hello");
              set.add("b");
              set.add("a");
              set.add("world");
              set.add("b");
 
              //不存重复元素,元素无序
              System.out.println(set);
             
              //迭代器
              Iterator it = set.iterator();
              while(it.hasNext()) {
                     System.out.println(it.next());
              }
       }
}

2. HashSet

2.1 概述

此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。

2.2 案例 获取HashSet里的元素

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
 
public class TestMap {
    public static void main(String[] args) {
       HashSet set = new HashSet();
       set.add("a");
       set.add("e");
       set.add("b");
       set.add("a");
       set.add("b");
      
       System.out.println(set);//无序,不重复
      
       Iterator it = set.iterator();
       while(it.hasNext()) {
           System.out.println(it.next());
       }
      
    }
}

3. Map接口

3.1 概述

java.util  接口 Map<K,V>

类型参数: K - 此映射所维护的的类型
V - 映射的类型。

也叫哈希表、散列表。常用于存 键值对 结构的数据。其中的键不能重复,值可以重复.

在这里插入图片描述

3.2 特点

  • 可以根据键 提取对应的值

  • 键不允许重复,如果重复值会被覆盖

  • 存放的都是无序数据

  • 初始容量是16,默认的加载因子是0.75

在这里插入图片描述

3.3 继承结构

在这里插入图片描述

3.4 常用方法

void clear()
          从此映射中移除所有映射关系(可选操作)。

 boolean containsKey(Object key)
          如果此映射包含指定键的映射关系,则返回 trueboolean containsValue(Object value)
          如果此映射将一个或多个键映射到指定值,则返回 trueV get(Object key)
          返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 nullboolean isEmpty()
          如果此映射未包含键-值映射关系,则返回 trueV put(K key, V value)
          将指定的值与此映射中的指定键关联(可选操作)。

 void putAll(Map<? extends K,? extends V> m)
          从指定映射中将所有映射关系复制到此映射中(可选操作)。

 V remove(Object key)
          如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。

 int size()
          返回此映射中的键-值映射关系数。

Set<Map.Entry<K,V>> entrySet()
          返回此映射所包含的映射关系的 Set 视图。

3.5 案例 测试常用方法

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
 
public class TestMap {
       public static void main(String[] args) {
              Map map = new HashMap ();
              map.put("001", "钢铁侠");
              map.put("002", "蜘蛛侠");
              map.put("003", "绿巨人");
              map.put("004", "灭霸");
              map.put("005", "美国队长");
              map.put("005", "凤姐");
              System.out.println(map.containsKey("001"));
              System.out.println(map.containsValue("美国队长"));
              System.out.println(map.isEmpty());
              System.out.println(map.get("003"));
              System.out.println(map.remove("001"));
              System.out.println(map.size());
              Map map2 = new HashMap ();
              map2.put("999", "刘德华");
map.put(null,null);//可以存入键为null,值也null的数据
 
              map.putAll(map2);
              System.out.println(map);
             
              //keySet()返回键的set集合,把map的key形成set集合
              Set set = map.keySet();
              System.out.println(set);
             
             
              //map集合的遍历,
              //方式1:keySet():把map中的可以放入set集合
              //遍历方式1:keySet ()
Set set = m.keySet();
              Iterator it = set.iterator();
              while(it.hasNext()) {
                     String key = (String) it.next();
                     String val = (String) m.get(key);
                     System.out.println(key+"="+val);
              }
      
              //遍历方式2:entrySet ()
Set set2 = m.entrySet();
              Iterator it2 = set2.iterator();
              while(it2.hasNext()) {
                     Entry en = (Entry) it2.next();
                     String key = (String) en.getKey();
                     String value = (String) en.getValue();
                     System.out.println(key+"=="+value);
              }
             
       }
}

4. HashMap

HashMap的键要同时重写hashCode()equals()

hashCode()用来判断确定hash值是否相同

equals()用来判断属性的值是否相同

-- equals()判断数据如果相等,hashCode()必须相同

-- equals()判断数据如果不等,hashCode()尽量不同

4.1 概述

基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。

HashMap底层是一个Entry数组,当存放数据时会根据hash算法计算数据的存放位置。算法:hash(key)%n,n就是数组的长度。

当计算的位置没有数据时,就直接存放,当计算的位置有数据时也就是发生hash冲突的时候/hash碰撞时,采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结点加入。

在这里插入图片描述

4.2 案例 读取HashMap的数据

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
 
public class TestMap {
       public static void main(String[] args) {
              HashMap map = new HashMap ();
              map.put(100, "刘德华");
              map.put(101, "梁朝伟");
              map.put(102, "古天乐");
              map.put(103, "周润发");
 
              //遍历方式1:keySet ()
              Set set = m.keySet();
              Iterator it = set.iterator();
              while(it.hasNext()) {
                     String key = (String) it.next();
                     String val = (String) m.get(key);
                     System.out.println(key+"="+val);
              }
      
              //遍历方式2:entrySet ()
             Set set2 = m.entrySet();
              Iterator it2 = set2.iterator();
              while(it2.hasNext()) {
                     Entry en = (Entry) it2.next();
                     String key = (String) en.getKey();
                     String value = (String) en.getValue();
                     System.out.println(key+"=="+value);
              }
       }
}

4.3 案例 字符串中的字符统计

接收用户输入的一串字符串,统计出现的每个字符的个数

import java.util.HashMap;
import java.util.Scanner;
public class TestCount {
       public static void main(String[] args) {
              //abacbcda
              String s = new Scanner(System.in).nextLine();
             
              //a 1  b 2  c 1
              HashMap<Character,Integer> map = new HashMap<>();
              //遍历字符串获取每个字符
              for(int i = 0;i<s.length();i++) {
                     //1,取出字符串中的每个字符
                     char c = s.charAt(i);
                    
                     //拿着字符查个数
                     Integer count = map.get(c);
 
                     //如果取出来是null,就存1,
                     if(count==null) {
                            map.put(c, 1);
                     }else {
                            //如果取出来有值,计数加1
                            map.put(c,count+1);
                     }
              }
              System.out.println(map);
       }
}

4.4 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,当然负载因子可以根据自己的实际情况进行调整。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值