Java使用Lambda实现字符串出现次数最多的字符查找

2024-06-02 01:58

本文主要是介绍Java使用Lambda实现字符串出现次数最多的字符查找,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

问题引入:

给定字符串,写代码找出在字符串中出现次数最多的字符,出现次数相等的字符按照字典序输出。

问题剖析:

  • 考虑错误处理(字符串为空)
  • 考虑出现最多次数的字符不是一个,也即存在出现次数相等的字符
  • 出现次数相同的字符需要按照字典顺序排序

代码剖析:

package com.nokia.pats;import com.google.common.base.Strings;  // used guava libraryimport java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;public class MostOccurLetters {public MostOccurLetters() {}public List<Map.Entry<String, Integer>> countTheMostOccurLetters(String letters) {/** 1. if the input argument is not reasonable, just return an * empty List, which means no letter comply to the rule of the * question.*/if (Strings.isNullOrEmpty(letters)) { return Collections.emptyList();}/** 2. create one temp map to store the splitted letters, with corrsponding counter.*/Map<String, Integer> lettersByCount = new HashMap<>();for (char c : letters.toCharArray()) {lettersByCount.put(String.valueOf(c),lettersByCount.getOrDefault(String.valueOf(c), 0) + 1);}/** 3. below code with lambda will sort the sort the map by the*  counter, if the counter is equal, sort with the key by dic * sequence.*/List<Map.Entry<String, Integer>> result = lettersByCount.entrySet().stream().sorted(Comparator.comparing(Map.Entry<String, Integer>::getValue).reversed().thenComparing(Map.Entry<String, Integer>::getKey)).collect(Collectors.toList());/** 4. filter out the items which comply to the rule, which*  eauals = the most occur letters.*/return result.stream().filter(entry ->entry.getValue() == result.get(0).getValue()).collect(Collectors.toList());}
}
  1. 代码使用了google流行的guava库,库中有很多有用的工具类,减少再次造轮子的可能性。本代码中使用了guava中的Strings工具类,能对String做一些常用的操作,包括本代码中使用的字符串的Null和empty判断。
  2. 创建一个临时的map容器,用于存储分割自字符串的字符,并实现字符的统计。键是字符本身,值是出现次数。
  3. 实现对上述容器的排序,首先对次数进行一次排序,如果出现的次数相同则进行第二次排序,得到一个有序容器表述。
  4. 开始过滤和第一个元素出现次数相等的元素,并将结果返回。

至此,完成对代码的编写,下边对代码进行UT cover。

package com.nokia.pats;import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;import java.util.List;
import java.util.Map;public class MostOccurLettersTest {private MostOccurLetters mostOccurLetters;@Beforepublic void setUp() {mostOccurLetters = new MostOccurLetters();}@Testpublic void should_return_empty_list_when_input_is_null() {String letters = null;List<Map.Entry<String, Integer>> mostoccurs = mostOccurLetters.countTheMostOccurLetters(letters);// should return empty listAssert.assertTrue(0 == mostoccurs.size());}@Testpublic void should_return_empty_list_when_input_is_empty() {String letters = "";List<Map.Entry<String, Integer>> mostoccurs = mostOccurLetters.countTheMostOccurLetters(letters);// should return empty listAssert.assertTrue(0 == mostoccurs.size());}@Testpublic void should_return_the_most_occur_letters() {String letters = "abccddrrrrr";List<Map.Entry<String, Integer>> mostoccurs = mostOccurLetters.countTheMostOccurLetters(letters);// should has only one items in letters which is "r":5;Assert.assertTrue(1 == mostoccurs.size());Assert.assertEquals("r", mostoccurs.get(0).getKey());Assert.assertEquals(new Integer(5), mostoccurs.get(0).getValue());}@Testpublic void should_return_2items_when_exist_two_equal_occur_letters() {String letters = "cccbbaaa";List<Map.Entry<String, Integer>> mostoccurs = mostOccurLetters.countTheMostOccurLetters(letters);// should return two items, with corrsponding sort first on counter, then by letter itself.Assert.assertTrue(2 == mostoccurs.size());Assert.assertEquals("a", mostoccurs.get(0).getKey());Assert.assertEquals(new Integer(3), mostoccurs.get(0).getValue());Assert.assertEquals("c", mostoccurs.get(1).getKey());Assert.assertEquals(new Integer(3), mostoccurs.get(1).getValue());}
}
  1. 第一个UT测试,如果字符串为null,那么返回的list为空。在java代码尽量不要返回null,在返回值是List的情况下,如果允许返回null,那么会出现“null”和“list空”两个模糊的语义,因为这两个均可以表示没有意义或者不存在的含义 ,于是会对代码的可读性有伤害。另外,也可以考虑Java的Optional。
  2. 第二个UT测试,如果字符串的长度为0,那么返回长度为0的List。和第一个UT测试类似。
  3. 第三个UT测试,如果一段字符串中出现只有一个字符出现的次数最多的情况下,最后返回的List的长度必须是1,然后对应的键和值,是出现次数最多的字符及其次数。
  4. 第四个UT测试,如果出现两个字符出现的次数相等的情况下,返回的List长度是2,第一个元素是字典序在前面的元素,第二个元素是字典序次之的元素,以此类推。

这篇关于Java使用Lambda实现字符串出现次数最多的字符查找的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1022721

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数