java - 在Java中, "decorate and sort"简洁的实现?

标签 java comparator

我是第一次学习 Java(我之前的经验是 Python 和 Haskell)。我遇到的情况是,在 Python 中,需要“装饰和排序”习惯用法。如下所示(代码未经测试,但大致正确):

origList = <something>
decorated = sorted( [(evalFunc(item), item) for item in origList] )
finalList = [item for _, item in decorated]

通过选择不同的 evalFunc您可以选择排序方式。

在 Java 中,我正在编写一个程序,该程序通过从音符列表中进行选择、评估每个音符的“适合度”并选择最佳音符来创作音乐。我有一门代表音符的类(class):

class Note {
   ...
}

我有一个类,将音符的适合度表示为两个值,即它的好坏(是的,这些是我的程序中的独立概念)。注意:在Python或Haskell中,这只是一个2元组,但我的理解是Java没有通常意义上的元组。我可以把它做成一对,但是像List<Pair<Type1,Pair<Type2,Type3>>>这样到处声明变量会变得很笨拙。 。 (顺便说一句,我认为 Java 也没有类型别名,这可以让我缩短声明。)

class Fitness {
    double goodness;
    double badness;
}

评估适应度的函数需要访问除 Note 之外的几条数据。我们会说它是“Composition”类的一部分:

class Composition {
    ... data declared here ... ;

    public Fitness evaluate(Note n) {
    }
}

我希望能够比较Fitness按数字顺序排列的对象。比较的方法有两种:好坏可以用数字来比较,看情况。

class CompareFitnessByGoodness implements Comparator<Fitness> {
}

class CompareFitnessByBadness implements Comparator<Fitness> {
}

我想打包 Note连同它的适应度,这样我就可以按适应度对组合列表进行排序,然后选出最好的 Note .

class Together {
    public Note;
    public Fitness;
}

我想对 List<Together> 进行排序或因善,或因恶。所以我可能需要:

class CompareTogetherByGoodness implements Comparator<Together> {
    ...
}

class CompareTogetherByBadness implements Comparator<Together> {
   ...
}

最终我会写一些类似的东西

Note pickBest(List<Together> notes) {
    // Pick a note that's not too bad, and pretty good at the same 
    // time.

    // First sort in order of increasing badness, so I can choose
    // the bottom half for the next stage (i.e. the half "least bad"
    // notes).
    Collections.sort(notes, new CompareTogetherByBadness());
    List<Together> leastBadHalf = notes.subList(0, notes.size()/2);

    // Now sort `leastBadHalf` and take the last note: the one with
    // highest goodness.
    Collections.sort(leastBadHalf, new CompareTogetherByGoodness());

    return leastBadHalf.get(leastBadHalf.size()-1);
}

哇!对于 Haskell 或 Python 中的几行代码来说,这是大量的代码。有更好的方法吗?

编辑:

解决一些问题的答案。

“你不需要装饰。”嗯,我的适应度计算非常昂贵,所以我想为每个音符计算一次,并保存结果以供以后访问。

“将好/坏存储在注释中。”纸币的好坏并不仅仅取决于纸币的属性。它仅在上下文中才有意义并且可以改变。因此,这是一个建议,我添加可变状态,该状态仅在某些情况下有意义,或者如果存在意外改变它的错误,则完全错误。这很丑陋,但也许是 Java 的必要拐杖。

最佳答案

遵循你已有的东西

origList = <something>
decorated = sorted( [(evalFunc(item), item) for item in origList] )
finalList = [item for _, item in decorated]

这在现代 Java 中是等价的:

给定您的合成对象:

Composition composer = ...;

以及注释列表:

List<Note> notes = ...;

然后你可以这样做:

List<Together> notesAllTogetherNow = notes.stream()
                                          .map(note -> new Together(note, composer.evaluate(note)))
                                          .sorted(new CompareTogetherByGoodness())
                                          .collect(Collectors.toList());

要获得最佳注释,您可以采取进一步措施:

Optional<Note> bestNote = notes.stream()
                               .map(note -> new Together(note, composer.evaluate(note)))
                               .sorted(new CompareTogetherByBadness())
                               .limit(notes.size() / 2) // Taking the top half
                               .sorted(new CompareTogetherByGoodness())
                               .findFirst() // Assuming the last comparator sorts in descending order
                               .map(Together::getNote);

关于java - 在Java中, "decorate and sort"简洁的实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50730007/

相关文章:

Java 数字错误

java - 比较器排序不正确

C++ 自定义比较器不工作 MWE

java - 使用监听器的正确方法是什么?

Java正则表达式匹配器动态字符串问题

java - 我可以从静态方法调用非静态方法吗?

java - 另一个 "Comparison method violates its general contract!"

java - 在 Java 中使用 stream.sorted() 进行排序

java - 将用户输入的句子中的每个单词与另一个文本进行比较(android/java)

java - java打印票证中的格式文本