当前位置: 首页 > 知识库问答 >
问题:

Java中的Lambda表达式如何帮助排序?帮我理解

奚修伟
2023-03-14

这里的任务是,我得到输入字符串,例如树,并根据频率排序,输出应该是'eetr'/'eert',因为e重复2次和t, r频率是1.

我有这个代码,什么是它遍历字符串,把所有字符在字符串中的Hashmap与他们的频率和优先级队列用于排序他们降序,之后的结果是采取在字符串生成器,

但我需要一些帮助来理解优先级队列参数中使用的lambda函数。这是我的功能。

public String frequencySort(String s)          // lets assume that input string is "tree"
{
    HashMap<Character,Integer> map = new HashMap<>();
    for(char c:s.toCharArray())
    {
        map.put(c,map.getOrDefault(c,0) + 1);
    }                                                       //  now after this my HashMap will have values (t,1),(r,1),(e,2)

PriorityQueue<Character> maxHeap = new PriorityQueue<>((a,b) -> map.get(b) - map.get(a));  //my question is about this constructor in priority queue, There are just two input parameters , how subtracting two things will help in sorting ??

maxHeap.addAll(map.keySet()); // i guess the keyset is now 't,r,e'  but constructor has only 2 parameters, what is going on ? How will the constructor help in setting the sorting behaviour of prioroty queue? 

StringBuilder result = new StringBuilder();

    while(maxHeap.isEmpty())
    {
        char current = maxHeap.remove();
        for(int i=0;i < map.get(current);i++)
        {
            result.append(current);
        }
    }

}

有人能用函数中的“树”来解释流程吗

共有3个答案

华萧迟
2023-03-14

我认为,使用这样的“隐式”比较器可能会非常令人困惑。PriorityQueue构造函数(自Java8起)被定义为对一个it参数采取java.util.比较器比较器接口指定了一个函数比较(),该函数接受两个参数,并返回一个整数。整数的符号指示哪个元素较大。这就是为什么在OP中,两个元素的值被减去——如果它们相等,结果将为零。如果一个比另一个大,结果要么是正的,要么是负的。PriorityQueue实现使用这些应用于许多元素的结果来确定它们应该放置的顺序。

我认为,在lamba表达式出现之前,这种逻辑是相当直观的。现在,比较器被声明为一个“函数接口”。这意味着可以直接从lamba表达式创建接口的匿名实例化。Java编译器知道PriorityQueue构造函数的参数是一个比较器,并且它知道基于lambda表达式实例化比较器。在本例中,lambda表达式包含两个参数,ab比较器接口有一个方法,它接受两个参数--比较(a, b)。因此在代码生成中可以使用匹配。

因此,Java生成代码,用比较器的定义替换lamba表达式,比较器的compare(a,b)方法是lambda函数的实现(即-

我认为,这可能令人困惑的是,Comparator接口本身是完全不可见的——您需要知道,PriorityQueue有一个Comparator参数,Comparator是一个函数接口,它有一个带有两个参数的方法,compare(),与lamba表达式匹配。

屠华辉
2023-03-14

这与Scala中的wordCount示例非常相似。但它计算字符串中的单词,但程序计算单词中的字母。非常相似。

然而,地图输出将如下:

(t,1)、(r,1)、(e,2)

地图。获取(b)-地图。get(a)仅用作比较器。如果映射。获取(b)-地图。获取(a)为负值,这意味着map。获得(b)

请参阅Javadoc了解PriorityQueue:基于优先级堆的无限优先级队列。优先级队列的元素根据其自然顺序排序,或由队列构造时提供的比较器排序,具体取决于使用的构造函数

闻人献
2023-03-14

但是构造函数只有2个参数

不,仔细看,在new PriorityQueue(…) ,即<代码> 部分只包含一件事-(a,b)-

如果您发现lambda表达式令人困惑,那么将代码重写为:

new PriorityQueue<>(Comparator.comparing(map::get).reversed());

意图应该更清楚,它做的事情大致相同。我们正在创建一个优先级队列,它应该通过比较我们通过对每个元素应用map.get得到的整数来比较它的元素。换句话说,给定两个元素ab,队列应该通过比较map.get(a)map.get(b)来决定哪个元素排在第一位。并且您想要相反的升序(即降序)。

在原始代码中,而不是使用返回比较器的比较方法

  • 如果第一个参数比第二个参数“小”,则返回一个负整数
  • 如果参数相等,则返回0
  • 如果第一个参数“大于”第二个参数,则返回一个正整数

从数学上观察,如果map.get(a)

现在你应该明白为什么map。获取(b)-地图。get(a)通过比较通过应用map得到的整数,给出相反的顺序。获取每个元素的

杂项说明:

  • 使用减法实现比较器实际上不是一个好主意,因为溢出。更多信息请参见此处

 类似资料:
  • 我想对我的文件内容进行排序。我的文件内容是学生姓名,他们的学生编号,他们的班级,他们的成绩。这些数据由“;”分隔。首先,我需要计算平均值和字母等级。我已经计算过了,但是我需要将所有内容写入另一个文件,顺序必须是最高等级到最低等级。我该怎么办?

  • 我有一些图像只包含数字和分号。 您可以在这里看到更多:https://imgur.com/a/54dsl6h 它们在我看来非常干净和简单,但Tesseract认为它们是空的“页面”()。 我怎么做才能让Tesseract更好地识别角色?

  • /**程序可以将十进制转换为二进制并报告是否使用了非法字符*程序不能将二进制转换为十进制*/import java.util.scanner; /***这个类包含一个完整的程序,只有一个main()方法,用于*将非负十进制整数(即以10为基数的整数)转换为*正二进制整数(即以2为基数的整数)。要*转换的值是从命令行读入的。*/public class BaseConversions2{public

  • 问题内容: 我有以下示例字符串 我只对 test6IAmInterestedIn 感兴趣,它位于第四个斜杠之后,可以包含3个字符,多个字母并以3个数字结尾,即。 我想在上述正则表达式中添加的内容是,我总是在匹配的第四个斜杠之后选择字符串。我该怎么办? 问题答案: 你可以试试这个演示 哪里 匹配包含正斜杠的4个块 捕捉您想要的图案

  • 记住命令,特别是命令的用法挺难,不同的命令都有各自的可以使用的参数。一般的命令都支持 --help 参数,它会为你显示命令的帮助信息,比如可用的参数,参数的作用等等。或者也可以使用 man 命令查看命令的帮助手册。 查看帮助,例如看一下 curl 命令的帮助信息: curl --help 返回信息截取: Usage: curl [options...] <url> Options: (H) me

  • 问题内容: 我研究了Java内存模型,并发现了重新排序问题。一个简单的例子: 重新排序非常不可预测且很奇怪。另外,它破坏了抽象。我想处理器架构必须有充分的理由来做一些对程序员来说很不方便的事情。 那是什么原因 关于如何处理重新排序有很多信息,但是我找不到有关 为什么 需要重新排序的任何信息。人们到处都只说“这是因为有一些性能优势”。例如,在存储之前有什么性能好处? 您可以推荐一些有关此的文章,论文