Day18-1.Map集合实现类 、Collections工具类

本文详细介绍了Java中的Map集合类及其子类,包括TreeMap的有序性、HashMap的哈希原理、LinkedHashMap的有序存储和HashMap与Hashtable的区别。通过实例演示如何统计字符出现次数。同时涵盖了线程安全性的讨论和Collections工具类的应用。

1 Map集合实现类

  1. 概述:Map集合为双列集合的顶层接口,底层根据不同的实现方式,有不同的实现类
  2. 实现类:
    TreeMap和HashMap

2 TreeMap集合

  1. 概述:是一个双列集合,是Map集合的实现类
  2. 特点:
    (1)集合中的key值是唯一的,元素是无序的
             key值唯一的原理和TreeSet原理相同
             元素排序的方式,是根据key来实现排序,排序的方式和TreeSet方式一样
    (2)TreeSet集合和TreeMap集合的关系:
             TreeSet集合底层是由TreeMap实现的

3 HashMap集合

  1. 概述:是一个双列集合,属于map集合的实现类。
  2. 特点:
    (1)集合中的key值不可以重复,元素是无序的
             key值去重和无序的原理,跟昨天讲的HashSet一样
             通过key的哈希值来实现存储和取出

(2)HashSet集合和HashMap集合的关系:
               HashSet集合底层是由HashMap集合实现的

4 LinkedHashMap集合

  1. 概述:是一个双列集合,是HashMap集合的子类
  2. 特点:
    (1)本类没有特殊的方法,只能使用父类中继承的
    (2)集合中元素有序(存入和取出)
    可以跟根据key值保证元素的有序,可以记录下一个key的地址
    (3)集合中的key值唯一

5 练习

键盘录入一个字符串,统计每个字符出现的次数,并按照指定格式进行输出(按照元素录入字符的顺序输出)
例如,录入数据为:aaaabbccddd!@#@#KaTeX parse error: Expected 'EOF', got '#' at position 2: @#̲%cc66ff
打印出来:a有4个,b有2个,c有4个,d有3个,!有1个,@有3个,$有2个,% 有1个,6有2个,f有2个

代码

package demos2_map;

import java.util.LinkedHashMap;
import java.util.Map;

public class Test02 {
    public static void main(String[] args) {
        //统计一个字符串中   字符---个数
        //1、每一个字符和对应的个数都是一一对应的映射关系:想到使用,map
        //2、获取字符串中的每一个字符:
        //   判断该字符和次数  在map集合中有没有存储过
        //                  如果有存储过,表示需要将之前该字符对应个数取出+1,再存入
        //                  如果没有存储过,表示需要将该字符当做key,将1当做value存储到集合
        LinkedHashMap<Character,Integer> lin = new LinkedHashMap<>();
        String str = "aaaabbccddd!@#@#$@#$%cc66ff";
        for(char c:str.toCharArray()){
            if(lin.containsKey(c)){
                lin.put(c,lin.get(c)+1);
            }else{
                lin.put(c,1);
            }
        }

        //遍历存储过的字符和个数关系
        StringBuilder sb = new StringBuilder();
        for(Map.Entry<Character,Integer> en:lin.entrySet()){
            Character key = en.getKey();
            Integer value = en.getValue();
            sb.append(key).append("有").append(value).append("个,");
        }
        System.out.println(sb.substring(0,sb.length()-1));
    }
}

6 HashMap和Hashtable集合的区别【面试题】

  1. 相同点:
    (1)HashMap和Hashtable都是Java用于存储映射关系的集合,都是Map的实现类
    (2)底层都采用了哈希表存储数据。
    (3)两个类中的方法都相同
  2. 不同点:
    (1)版本不同,Hashtable是jdk1.0版本出现的,HashMap是jdk1.2版本出现的
    (2)线程安全性不同,Hashtable是线程安全的,HashMap是线程不安全的
    (3)HashMap集合操作元素的效率高,HashTable集合操作元素的效率低
    (4)Hashtable不能存储null键null值,如果存储,出现空指针异常
    HashMap可以存储null键null值

6.1 线程安全不安全类型小总结

  1. StringBuiler是线程不安全,使用效率高
    StringBuffer是线程安全,使用效率低
  2. HashMap线程不安全,使用效率高
    Hashtable线程安全,使用效率低
  3. ArrayList 线程不安全,使用效率高
    Vector 线程安全 ,使用效率低

7 Collections工具类

  1. 概述:本类是JDK提供的操作集合的工具类,类中定义了一些操作集合元素的方法
  2. 常用方法:
项目Value
binarySearch(List<? extends Comparable<? super T>> list, T key)通过二分查找法查找元素key在集合中的索引
frequency(Collection<?> c, Object o)获取集合中o元素出现的次数
max(Collection c)求出集合中的最大值
min(Collection c)求出集合中的最小值
reverse(List<?> list)反转集合中的元素顺序
shuffle(List<?> list)随机排列集合元素的顺序
sort(List<T> list)将集合中的元素进行升序排列
swap(List<?> list, int i, int j)交换集合中两个元素的位置
synchronizedList(List<T> list)将线程不安全的单列集合可以转换为安全的单列集合
synchronizedMap(Map<K,V> m)将线程不安全的双列集合转为安全的双列集合
任务描述 本关任务:编写一个能计算一段文本内容中出现单词的次数的降序排列的小程序。 相关知识 为了完成本关任务,你需要掌握: 1.如何统计相同单词的次数; 2.如何进行排序。 统计相同单词的次数 //使用map集合进行存储 String s="Day by Day"; Map<String,Integer> map=new HashMap<String,Integer>(); StringTokenizer tokenizer=new StringTokenizer(s); int count;//记录次数 String word;//单个单词 while(tokenizer.hasMoreTokens()){ word=tokenizer.nextToken(" "); if(map.containsKey(word)){ //拿到之前存在map集合中该单词的次数 count=map.get(word); map.put(word, count+1); }else{ map.put(word, 1); } } Set<Entry<String, Integer>> entrySet = map.entrySet(); for (Entry<String, Integer> entry : entrySet) { System.out.println(entry.getKey()+"-"+entry.getValue()); } 输出: by-1 Day-2 如何进行排序 使用Collections包装类。它包含有各种有关集合操作的静态多态方法。 //可根据指定比较器产生的顺序对指定列表进行排序。 Collections.sort(List<T> list, Comparator<? super T> c) 示例如下: //以上实例中的map集合为例 将map集合的每一项添加进list集合中 List<Map.Entry<String, Integer>> infos = new ArrayList<Map.Entry<String, Integer>>(map.entrySet()); Collections.sort(infos, new Comparator<Map.Entry<String, Integer>>() { public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { //前者-后者 升序 后者-前者 降序 return (o2.getValue() - o1.getValue()); } }); 输出: Day-2 by-1 编程要求 请仔细阅读右侧代码,根据方法内的提示,在Begin - End区域内进行代码补充,具体任务如下: 将指定文本(可以通过右侧文件目录下的src/step3/readme.txt查看)以降序的方式输出每个单词出现的次数。 测试说明 补充完代码后,点击测评,平台会对你编写的代码进行测试,当你的结果与预期输出一致时,即为通过。 预期输出: 参考右边测试集中的输出。 package step3; import java.util.Map; import java.util.HashMap; import java.util.StringTokenizer; public class StudentDemo{ //获取单词的数量 public Map<String, Integer> getWordCount(String str) { Map<String, Integer> map = new HashMap<String, Integer>(); //请在此添加实现代码 /********** Begin **********/ StringTokenizer tokenizer = new StringTokenizer(str); while (tokenizer.hasMoreTokens()) { String word = tokenizer.nextToken(); map.put(word, map.getOrDefault(word, 0) + 1); } // 2.map 转换为 List 以便排序 java.util.List<Map.Entry<String, Integer>> list = new java.util.ArrayList<>(map.entrySet()); // 3. 对 List 进行降序排序 java.util.Collections.sort(list, new java.util.Comparator<Map.Entry<String, Integer>>() { @Override public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { return o2.getValue().compareTo(o1.getValue()); } }); // 4. 创建一个 LinkedHashMap 来存储排序后的结果 Map<String, Integer> sortedMap = new java.util.LinkedHashMap<>(); for (Map.Entry<String, Integer> entry : list) { sortedMap.put(entry.getKey(), entry.getValue()); } // 5. 将 sortedMap 赋值给原始的 map 引用 map = sortedMap; /********** End **********/ return map; } }
最新发布
11-20
以下是完整的解决方案,包括对代码的详细解释以及相关问题。 --- ```java package step3; import java.util.Map; import java.util.HashMap; import java.util.StringTokenizer; public class StudentDemo { // 获取单词的数量,并按出现次数降序排列 public Map<String, Integer> getWordCount(String str) { Map<String, Integer> map = new HashMap<String, Integer>(); /********** Begin **********/ // 1. 使用 StringTokenizer 分割字符串为单词 StringTokenizer tokenizer = new StringTokenizer(str); while (tokenizer.hasMoreTokens()) { String word = tokenizer.nextToken(); // 使用 getOrDefault 简化判断:如果不存在则默认为0,加1后存入 map.put(word, map.getOrDefault(word, 0) + 1); } // 2.map 中的键值对(Entry)放入 List 中以便排序 java.util.List<Map.Entry<String, Integer>> list = new java.util.ArrayList<>(map.entrySet()); // 3. 使用 Collections.sort 对 list 按 value 值进行降序排序 java.util.Collections.sort(list, new java.util.Comparator<Map.Entry<String, Integer>>() { @Override public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { // 降序:后面的减前面的(o2 - o1) return o2.getValue().compareTo(o1.getValue()); } }); // 4. 创建一个 LinkedHashMap 来保持插入顺序(有序输出) Map<String, Integer> sortedMap = new java.util.LinkedHashMap<>(); for (Map.Entry<String, Integer> entry : list) { sortedMap.put(entry.getKey(), entry.getValue()); } // 5. 将排序后的结果赋给原 map 变量返回 map = sortedMap; /********** End **********/ return map; } } ``` ### ✅ **代码解释:** 1. **`StringTokenizer tokenizer = new StringTokenizer(str);`** - `StringTokenizer` 是 Java 工具类,用于将字符串按空格或指定分隔符拆分为单词。 - 默认以空白字符(空格、换行、制表符等)分割。 2. **统计词频:`map.put(word, map.getOrDefault(word, 0) + 1);`** - 这是统计频率的经典写法。若 `word` 未出现过,默认值为 `0`;否则取当前计数并加 `1`。 - 相比原始 `if-else` 判断更简洁高效。 3. **转换成 List 排序:`new ArrayList<>(map.entrySet())`** - `entrySet()` 返回所有键值对集合- 需要放入 `List` 才能使用 `Collections.sort()`。 4. **自定义比较器实现降序排序:** ```java return o2.getValue().compareTo(o1.getValue()); ``` - 因为我们要**按出现次数从高到低排序**,所以用 `o2.value - o1.value` 实现降序。 - 注意不能直接相减(可能溢出),所以使用 `Integer.compareTo()` 更安全。 5. **使用 `LinkedHashMap` 保持排序结果:** - 普通 `HashMap` 不保证顺序。 - `LinkedHashMap` 按插入顺序保存元素,因此可以保留我们排序后的结构。 6. **最终返回的是已按频次降序排列的 Map。** --- ### 示例输入与输出: 假设 `readme.txt` 内容如下: ``` apple banana apple cat dog cat apple ``` 程序输出应为(通过遍历返回的 map 输出): ``` apple-3 cat-2 banana-1 dog-1 ``` > ⚠️ 测评系统会自动读取文件内容并调用 `getWordCount()` 方法验证结果是否正确。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值