使用3个不同类别的可比较

时间:2018-05-20 06:51:25

标签: java object comparable

我正在尝试实现一个返回给定Comparable(通用)列表的最大对象的函数。

我有3个类,我已经实现了他们的compareTo方法,如果它比其他大,则返回1,如果小于其他,则返回-1,如果它们相等,则返回0。

现在我的问题是了解如何使用通用输入COmparable列表。

这是我的函数的签名,以及我到目前为止编写的代码(拒绝对我有用):

public static Comparable<?> getMax(List<Comparable<?>> ls) {
    LinkedList<Comparable<?>> tmpComp = new LinkedList<Comparable<?>>();
    for (Comparable<?> c : ls)
        tmpComp.add(c);
    Comparable<?> maxObj = tmpComp.get(0);
    for (Comparable<?> c : tmpComp)
        if (c.compareTo(maxObj) > 0)
            m = c;
    return m;
}

我正在编写一个包含用户的系统和广告。用户和广告这两个在我们的compareTo方法中都有“利润”字段的类就是比较两者中的哪一个(这个或其他)有更多的利润,然后根据它返回正确的值。第三个类通过另一个字段进行比较,该字段也是一个int,表示Quest的级别(int)。

此外,if语句特别为我提供了“不适用于参数”类型的错误。

任何线索?

提前致谢!

3 个答案:

答案 0 :(得分:1)

阅读你的评论,我建议你重新设计你的模型:

interface ProfitGenerating {
    double getProfit();
}

class User implements ProfitGenerating {
    ...
}

class Advert implements ProfitGenerating {
    ...
}

List<ProfitGenerating> profits = ...;

Optional<ProfitGenerating> maxProfit = profits.stream()
    .max(Comparator.comparingDouble(ProfitGenerating::getProfit));

答案 1 :(得分:0)

MạnhQuyếtNguyễn的答案很好。但它没有考虑到你有多种潜在类型T的情况,这似乎是你的情况。

所以在那种情况下,只需用一个类包装你的各个类并使用他的解决方案。

如果你有一个User类和一个Ad类,那么创建一个这样的包装器:

class ProfitMaker implements Comparable<ProfitMaker> {
    User user;
    Ad ad;

    public int compare(ProfitMaker p) {
         //check my profit and compare with profit of p
    }
}

将该课程用作&#34; T&#34;当使用来自MạnhQuyếtNguyễn的getMax时。

或者,使用界面

 interface ProfitMaker extends Comparable<ProfitMaker> {
      int getProfit();
 }

让您的用户和广告类都实现该界面,并将该界面用作&#34; T&#34;以及来自MạnhQuyếtNguyễn的getMax方法。

答案 2 :(得分:0)

你的三个班级必须相互比较。为此,他们需要实现Comparable<SomeX>,其中SomeX是他们最低的共同超类。在最糟糕的情况下,SomeXObject

如果是这种情况,您只需执行以下操作:

ls.stream().max(Comparator.naturalOrder())

或者,您可以捕获Comparable<...>中的比较语义,然后执行:

,而不是强制您的类实现Comparator<...>
ls.stream().max(comparator)

对于类型不是真正“自然”的订单或可能存在不同订单的情况,使用比较器会更好。我认为这就是这种情况,因为您实际上比较了不同类型的实例。很难说某些命令对于这些实例来说是“自然的”,因为它们甚至不属于一种类型。

如果您根据他们共享的某些属性(例如int getProfit())比较您的实例,那么创建一个像Profitable这样的公共界面是有意义的。然后你可以这样做:

ls.stream().max(Comparator.comparintInt(Profitable::getProfit))

请注意,如果您对私有类型进行比较,则应使用comparingInt / comparingLong / comparingDouble代替comparing,以避免不必要的装箱和拆箱。

如果由于某种原因无法创建和实现Profitable等常用界面,您仍然可以使用comparingInt并喜欢。你只会有一个更丑陋的lambda:

ls.stream().max(Comparator.comparintInt(l -> {
    if (l instanceof Ad) { return ((Ad) l).getProfit(); }
    else if (l instanceof Ransom) { return ((Ransom) l).getProfit(); }
    // ...
    else { throw new IllegalArgumentException(...); }
}))