java api06(HashMap集合 方法 遍历方法 衍生类的区别 jdk9新特性 导包教程 )(计算⼀个字符串中每个字符出现次数练习)

Map<K,V>(I)
1.Map是最大的接口,也就是说往上没有父接口了,也就意味着没有继承Iterable接口,所以不能使用迭代器进行遍历.

2.特点:
1).Map是一个映射表,一个双列集合,一个元素包含两个值(key - value)
2).key(键)是唯一的,value(值)是允许重复的
3).因为key是唯一的,所以可以根据key获得value

3.Map集合的分支
| - HashMap©
|- LinkedHashMap©
| - HashTable©
| SortedMap(I)
| - TreeMap©
| - ConcurrentHashMap©

4.HashMap©
1).底层实现: 哈希表(散列表)
底层数据结构:
JDK1.8之前: 数组 + 单向链表
JDK1.8之后: 数组 + 单向链表|红黑树

红黑树图解
在这里插入图片描述

2).特点:
a.是一个无序的集合,存储元素和取出元素的顺序有可能是不一致
b.如果key完全一样,则value会被覆盖,等同于修改元素(value)
c.HashMap的key允许只有一个null值,但是value可以允许有多个null值

3)存储过程:
a.计算key的hashCode值,确定位置
b.判断位置上是有存在元素
c.如果没有元素,则直接存入
d.如果有元素,则使用equals进行判断是否一致
需要跟该位置上的链表中所有元素进行对比
e.如果一致,则进行覆盖
f.如果不一致,存入到链表尾部(头部)
在这里插入图片描述

注意:在JDK1.8以后,如果链表长度超过8,则变成红黑树进行存储.

4)初始容量大小
a.默认初始容量: 16
b.要进行扩容时:
* 如果存满再扩容,会造成链表多,效率低下
* 如果是过半就扩容,会占用内存空间
* 加载因子: 扩容条件
默认0.75 -> 容量达到75%进行扩容
扩容为原容量的2倍
使用的方法resize()

5)常用API:
V put(K key, V value)
V get(Object key)
V remove(Object key)
containsKey(Object key)
containsValue(Object value)
putAll(Map<? extends K,? extends V> m)

package api06.map;

import java.util.HashMap;

/*
    HashMap常用API
 */
public class MapDemo01 {
    public static void main(String[] args) {
        /*
             V put(K key, V value)
                在此映射中关联指定值与指定键。
         */
        //创建HashMap的对象
        HashMap<String, Integer> map = new HashMap<>();
        //键和值 组成 一个元素
        Integer v1 = map.put("小乔", 16);
        System.out.println("v1:" + v1);//v1:null
        Integer v2 = map.put("小乔", 17);
        //如果是相同的key ,那么value会进行覆盖
        System.out.println("v2:" + v2);//v2:16
        System.out.println(map);//{小乔=17}

        //{null=18, 貂蝉=18, 小乔=17}
        map.put(null, null);
        map.put("貂蝉",null);
        //{貂蝉=18, 小乔=17, 周瑜=18}
        System.out.println(map);
    }
}

package api06.map;

import java.util.HashMap;

/*
    HashMap常用API
 */
public class MapDemo02 {
    public static void main(String[] args) {
        /*
         V remove(Object key)
          从此映射中移除指定键的映射关系(如果存在)。
         */
        HashMap<String, Integer> map = new HashMap<>();
        map.put("小乔",17);
        map.put("周瑜",18);
        map.put("大乔",19);
        //删除 key = 小乔
        Integer v1 = map.remove("小乔");
        System.out.println("v1:" + v1);//v1:17
        //{大乔=19, 周瑜=18}
        System.out.println(map);
        //删除不存在的元素 - key
        Integer v2 = map.remove("张飞");
        //NullPointerException - 自动拆箱
        System.out.println("v2:" + v2);//v2:null
        System.out.println(map);//{大乔=19, 周瑜=18}

        System.out.println("---------------------------");

        /*
         V get(Object key)
          返回指定键所映射的值;如果对于该键来说,
           此映射不包含任何映射关系,则返回 null。
         */
        HashMap<String, Integer> map1 = new HashMap<>();
        map1.put("小乔",17);
        map1.put("周瑜",18);
        map1.put("大乔",19);
        Integer v3 = map1.get("小乔");
        System.out.println("v3:" + v3);//v3:17
        Integer v4 = map1.get("张飞");
        System.out.println("v4:" + v4);//v4:null

    }
}

5.Map集合的遍历
Set keySet()
返回此映射中包含的键的Set 集合

注意: 获得所有的key值,并且获得对应的Set类型集合

在这里插入图片描述

Collection values()
返回此映射中包含的值的 Collection集合。
注意: 获取所有的value值,并且获得对应的Collection
在这里插入图片描述

Set<Map.Entry<K,V>> entrySet()
返回此映射中包含的映射关系的 Set集合。
在这里插入图片描述

<Map.Entry<K,V>: 作为Map的内部接口存在
Entry<K,V>: 键值对
将entry作为一个元素,存入到Set集合中

     getKey() -> 获取键
     getValue() -> 获取值
package api06.map;
import java.util.*;

/*
    Map的遍历/迭代
 */
public class MapDemo03 {
    public static void main(String[] args) {
        /*
         Set<K> keySet()
          返回此映射中包含的键的 Set集合。
         */
        HashMap<String, Integer> map = new HashMap<>();
        map.put("小乔",17);
        map.put("周瑜",18);
        map.put("大乔",19);
        map.put("张飞",18);
        map.put("吕布",19);
        System.out.println(map);
        //取出所有的元素
        Set<String> set = map.keySet();
        //对set集合进行遍历 - foreach / 迭代器遍历
        Iterator<String> it = set.iterator();
        while (it.hasNext()){
            String s = it.next();
            System.out.print("," + s);//获取到的key值
            //通过调用get方法 -> 可以得到value
            Integer v1 = map.get(s);
            System.out.println(v1);
        }

        //foreach - 简易版迭代器
        for ( String s : set ){
            System.out.println(s);
            //通过调用get方法 -> 可以得到value
            Integer v1 = map.get(s);
            System.out.println(v1);
        }

        //foreach - 简易版迭代器 - 优化
        for ( String s : map.keySet() ){
            System.out.println(s);
            //通过调用get方法 -> 可以得到value
            Integer v1 = map.get(s);
            System.out.println(v1);
        }

        System.out.println("--------------------");

    /*
        方式二: Collection<V> values()
          返回此映射中包含的值的 Collection集合。
          特点: 只能获取到value值,不能通过value获取key
     */
        Collection<Integer> col = map.values();
        for(Integer i : col){
            System.out.print(i + ",");
            System.out.println();
        }


        System.out.println("------------------");
        /*
            方式三: Set<Map.Entry<K,V>> entrySet()
                返回此映射中包含的映射关系的 Set集合。
            Map.Entry<K,V> - 键值对
         */
        Set<Map.Entry<String, Integer>> set1 = map.entrySet();
        for (Map.Entry entry: set1){
            //获取entry中key
            Object s = entry.getKey();
            //获取entry中value
            Object v = entry.getValue();
            System.out.println(s + "= " + v);
        }
    }
}

计算⼀个字符串中每个字符出现次数练习

package api06.map;

import java.util.HashMap;

/*
    需求:
    计算⼀个字符串中每个字符出现次数。
      1.获得一个字符串(Scanner)
      2.创建Map集合,Key值是字符,value值是字符个数
      3.遍历字符串 -> 获得字符
      4.对字符进行判断,判断该字符是否存在map集合中
        如果Key存在:
          value++
        如果key不存在:
          put(c,1)

      判断key是否存在:
       1.containKey()
       2.get(key)
 */
public class MapWorkTest05 {
    public static void main(String[] args) {
        // 1.获得一个字符串(Scanner)
        String str = "aaaabbbccd";
        //2.创建Map集合,Key值是字符,value值是字符个数
        HashMap<Character, Integer> map = new HashMap<>();
        //3.遍历字符串 -> 获得字符
        for (Character c : str.toCharArray()){
            //4.对字符进行判断,判断该字符是否存在map集合中
            if(map.containsKey(c)){
                //c -> key
                //想要获取的是value值
                Integer value = map.get(c);
                value++;//个数+1
                map.put(c,value);
            }else{
                map.put(c,1);
            }
        }

        //遍历集合获取值
        for (Character c :map.keySet()) {
            Integer v = map.get(c);
            System.out.println(c + "," + v);
        }

    }
}

6.LinkedHashMap©
1)底层实现: 数组 + 双向链表
2)特点:
是一个有序的集合,存储元素和删除元素都是一致的

package api06.map;

import java.util.LinkedHashMap;

/*
     LinkedHashMap的使用
       插入有序
 */
public class LinkedHashMapDemo06 {
    public static void main(String[] args) {
        //{小乔=18, 大桥=12, 张飞=15, 周瑜=20}
        LinkedHashMap<String,Integer> map = new LinkedHashMap();
        map.put("小乔",18);
        map.put("大桥",12);
        map.put("张飞",15);
        map.put("周瑜",20);
        System.out.println(map);


    }
}

7.HashTable©
1)特点:
a.继承Dictionary类
b.线程安全的,效率较低
c.键和值都不允许有null值
2)子类:
Properties - 集合中唯一和IO流有有关的集合
作为配置文件使用

package api06.map;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedHashMap;

/*
    HashTable的使用
 */
public class HashTableDemo07 {
    public static void main(String[] args) {
        HashMap<String,Integer> map = new HashMap();
        map.put(null,18);
        map.put("大桥",12);
        map.put("张飞",null);
        map.put("周瑜",null);
        System.out.println(map);

        Hashtable<String, Integer> map1 = new Hashtable<>();
        //key存在null的情况
        //map1.put(null,18);//NullPointerException
        map1.put("大桥",12);
        //value存在null
        map1.put("周瑜",null);//NullPointerException
        System.out.println(map1);
    }
}

8.TreeMap©
作用: 对Map进行排序

package api06.map;

import java.util.Comparator;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;

/*
    TreeMap的使用 - 排序
      排序:
        1.自然排序
          实现接口: Comparable -> 重写方法: compareTo()
        2.自定义排序(比较器排序)
          实现接口: Comparator -> 重写方法: compare()
 */
public class TreeMapDemo08 {
    public static void main(String[] args) {
       TreeMap map = new TreeMap();
        map.put("小乔",18);
        map.put("大桥",12);
        map.put("张飞",15);
        map.put("周瑜",20);
        System.out.println(map);

        TreeMap<String,Integer> tree = new TreeMap(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.compareTo(o1);
            }
        });
        tree.put("小乔",18);
        tree.put("大桥",12);
        tree.put("张飞",15);
        System.out.println(tree);
    }
}

9.ConcurrentHashMap©
1)底层实现:
JDK1.7 数组(segment数组) + (Entry)链表
分段锁技术
底层数据结构:数组 + 链表

JDK1.8 CAS + Synchronized
       ->Compare And Swap

底层数据结构:数组 + 链表|红黑树

10.HashMap和hashTable和ConCurrentHashMap之间的区别
1)线程安全问题
2)父类/父接口
3)是否允许存在null
4)底层实现

11.JDK1.9的新特性 -> of
1)List接口,Set接口,Map接口里边新增的一个静态方法 - of,可以给集合一次性添加多个元素

2)注意:
a. of()只能适用于List接口,Set接口,Map接口,不适用接口的实现类

b. of()的返回值是一个不可改变的集合,否则会抛出异常:UnsupportedOperationException:不支持的操作异常

c. Set/Map集合在调用of()的时候,不能有重复值,否则会抛出异常: IllegalArgumentException: 非法的参数异常
package api06.map;

import java.lang.reflect.Array;
import java.util.*;

/*
    JDK1.9新特性
 */
public class JDK9Demo09 {
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<>();
        list.add(1);
        list.add(1);
        list.add(1);
        list.add(1);
        //of -> 使用静态方法调用
        //List<Integer> list1 = List.of(1, 3, 4, 5, 6);
        //UnsupportedOperationException - 不支持的操作异常
        //list1.add(1);
        //System.out.println(list1);


        HashMap<String, Integer> map = new HashMap<>();
        map.put("小乔",17);
        map.put("小乔",17);
        map.put("小乔",17);
        map.put("小乔",17);
        //使用Map的静态方法调用
        /*给的是相同的key值
           IllegalArgumentException: 非法的参数异常
         */
        //Map.of("xiapqio",1,"xiapqio",2);
        //Map.of("xiapqio",1,"张三",2);
        System.out.println(map);


        //不允许有重复值
        //IllegalArgumentException - 非法的参数异常
        //Set<Integer> set = Set.of(2, 2, 3);
        //Set<Integer> set = Set.of(2,3);
        //System.out.println(set);

    }
}


测试方法:
System.out.println() --> 打桩测试
Debug --> 断点测试
JUnit --> 单元测试

JUnit --> 以方法为单位,可以直接取代主方法

导入第三方jar包的步骤:
1.在工程中创建一个文件夹lib
2.将要导入的jar包进行复制到lib文件夹中
3.右键选中jar包, Add as Library 添加依赖

自定义类

package api06.map;

import java.util.Objects;

/*
    自定义类
 */
public class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public User() {
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object object) {
        if (this == object) return true;
        if (object == null || getClass() != object.getClass()) return false;
        User user = (User) object;
        return age == user.age &&
                Objects.equals(name, user.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, 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;
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值