【问题标题】:Java - Comparator Class for same attributes from different object typesJava - 来自不同对象类型的相同属性的比较器类
【发布时间】:2020-07-13 07:28:15
【问题描述】:

我有一个奇怪的问题:

我有两个班级,BookNewspaper。他们共享属性price。我必须实现一个PriceComparator,它显然将priceBookNewspaper 进行比较。我不是太有经验 - 特别是在 Java 中,但我最重要的解决方案是制作一个接口,它可以让我获得共同的价值观,我可以根据这些进行比较,但这是不可能的,原因有两个:

1) 我只能拥有 BookNewspaperMainPriceComparator 类,并且不允许在同一个 .java 文件中创建另一个类/接口。

2) 我必须使用一个包含BookNewspaper 的列表

对此我的解决方案可能是创建一个List<Object>,然后使用强制转换比较通用对象以通过它们的 getter 获取它们的值,但这对我来说似乎很笨拙,但我认为必须有更好的解决方案我想不出一个。我希望我的问题是有道理的。谢谢!

【问题讨论】:

  • 显而易见的解决方案是为包含价格获取器的书籍和报纸创建一个通用的超类/接口。但是,既然你说这是明确禁止的,我也没有其他办法,只能使用 List<Object> 并进行强制转换。如果ObjectBookNewspaper 的唯一公共超类/接口,那么就没有其他方法可以定义同时接受这两个类的List。
  • @OHGODSPIDERS 好的,那我就在正确的轨道上,谢谢。我根本不喜欢这个解决方案,因为它看起来不必要地复杂。
  • 这个作业试图教你一些不好的编程习惯。在现实世界中,Book 和 Newspaper 之间会有一些共同的接口或对象(我称之为“PrintedWork”。说实话,报纸的价格与书籍的价格相差很大。
  • @NomadMaker 我知道。这门课的作业很奇怪。一个例子是一个对象的构造函数,它只能包含两个属性,而类却有三个。绝对没有理由,因为无论如何输入都是硬编码的。而且你不需要练习使用 setter。

标签: java list comparator


【解决方案1】:

如果您不允许在同一个 .java 文件中创建另一个类/接口,请单独创建您的接口。例如,

Priceable.java

public interface Priceable {
    double getPrice();
}

Book.java

public class Book implements Priceable{
    // ...
    int price;

    @Override
    public double getPrice() {
        return price;
    }
}

Newspaper.java

public class Newspaper implements Priceable{
    // ... other
    private double price;

    @Override
    public double getPrice() {
        return price;
    }
}

现在您可以定义一个Comparator<Pricable> 来比较价格。例如,

Comparator<Priceable> products = (o1, o2) -> (int) (o2.getPrice() o1.getPrice());

【讨论】:

  • Comparator.comparingDouble(Priceable::getPrice) 会是更好的比较器。
  • 我同意,但我相信 OP 更关心设计而不是比较本身。
  • 这是我一开始想到的解决方案,但这是一个作业,我只能交Book.javaNewsPaper.javaMain.javaPriceComparator.java。不允许其他文件。
  • 如果只能上交4个文件,问题在哪里呢?该解决方案还包括 4 个文件...
  • 顺便说一句,当您有Comparator&lt;Priceable&gt; 时,为什么还需要PriceComparator
【解决方案2】:

@Themelis 答案是 IMO 更合适(并且可能更有效)的解决方案。但如果有人对此感兴趣,可以使用反射的替代方法:

    Function<Object, Double> keyExtractor = o -> {
        try {
            Field field = o.getClass().getDeclaredField("fieldName");
            field.setAccessible(true);
            Double value = (Double) field.get(o);
            field.setAccessible(false);
            return value;
        } catch (Exception e) {
            return -1D;
        }
    };
    Comparator<Object> comparing = Comparator.comparing(keyExtractor, Double::compareTo);
    List<Object> objects = new ArrayList<>(List.of(new A(1), new B(3), new A(2), new B(0)));
    objects.sort(comparing);

注意:如果您传入一个没有声明字段 fieldName 类型为 double 的类的对象,则将抛出 NoSuchFieldExceptionClassCastException 并返回 -1 进行比较,从而使这些对象成为排序后在列表的开头。

【讨论】:

    猜你喜欢
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-20
    • 2023-03-19
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多