【问题标题】:Same sorting algorithm for objects of different classes (Java)不同类对象的相同排序算法(Java)
【发布时间】:2021-01-10 01:55:44
【问题描述】:

现在我有一个排序算法,它以随机顺序获取一个对象数组,根据值属性将它们排序到一个新数组中并返回排序后的数组(特别是一个 ArrayList,尽管我不相信它会相关对于我的问题)。对于我的任务,我现在被指示根据这些不同对象自己的值属性从最高到最低的顺序对另一个不同对象的数组进行排序。我不想通过在几个地方更改对象和属性名称来复制粘贴我已经实现的算法,或者只是以 O(n^2) 的顺序直接对其他对象进行排序,我想以某种更通用的方式重用我当前的算法。为了更清楚:

new Array<ClassA> a;
new Array<ClassB> b;

public Array<ClassB> sort(Array<ClassB> input){
    //sort based on certain attribute in ClassB;
    return sortedArray;
}

我想变成:

new Array<ClassA> a;
new Array<ClassB> b;

public Array<ClassB> sort(Array<Object> input, Attribute x){
    //sort based on attribute of Object where which attribute is given as a parameter x;
    return sortedArray;
}

我知道这可能比我的书面解释更令人困惑,所以更清楚(我希望)我希望将我的排序算法变成类似于 python 内置函数的东西: 排序(可迭代,键=无,反向=假)

我实现的算法是作业的一部分,所以我不能用库中的东西替换它。如果您认为我的整个问题很愚蠢,那么请考虑一下英语不是我的母语,不-我对编程术语一点也不熟悉,是的-我是一个非常糟糕的程序员。然后继续你的一天!但是,如果您认为可以给我一个合理的答案,将不胜感激:D

【问题讨论】:

  • 我不完全理解您的问题,但也许Comparable 界面可以帮助您?
  • 看看java的Comparator类(或Comparable接口)以及如何与Collection.sort一起使用。
  • 在java中,您可以使用接口Comparator按一个或多个字段排序,构建自己的比较器并使用它们对数组进行排序。
  • 也尝试阅读 Java 中的泛型。

标签: java arrays algorithm sorting


【解决方案1】:

public Array&lt;ClassB&gt; sort(Array&lt;Object&gt; input, Attribute x){

这会将任意对象数组转换为包含ClassB 实例的数组,这显然不是它的工作原理。

Array&lt;Object&gt; input

这并不意味着你认为它意味着什么。 Array&lt;ClassB&gt; 不是Array&lt;Object&gt; 的有效值。毕竟,我可以将字符串添加到Array&lt;Object&gt;(字符串是对象!),但我不能将字符串添加到Array&lt;ClassB&gt;。在计算机技术术语中,Java 中的基本类型(如 NumberInteger)是协变的 - 任何作为 X 子类型的实例也是 X:整数也是数字,是也是一个对象。但是类型 args 是不变的。任何属于 X 子类型的实例都与 X 不兼容:List&lt;Integer&gt; 不是List&lt;Number&gt;。这是因为这就是它的工作原理,正如我在上面展示的:您可以将双打添加到 List&lt;Number&gt;

您可以选择不同的差异:List&lt;? extends Number&gt;List&lt;? super Number&gt; 这样做。不过,您不需要它来解决这个问题。

泛型链接事物。这就是你想要的:接受一些东西的数组,然后返回一个相同的数组:

public <T> Array<T> sort(Array<T> input, Attribute x) {}

这说:有一些类型T。不知道它是什么。然后这个 T 用于链接事物:无论输入数组的类型是什么?输出数组具有相同的类型。

这是你想要的。

Attribute x

无法以编程方式引用属性。幸运的是,您实际上并不需要属性。你需要一个函数:给定一些T,提供一个值;一个,你现在如何固有地排序。这个功能是如何工作的?你不在乎。只要它是一致的(为任何给定实例返回相同的值),您就可以根据该映射值对其进行排序。所以,你不想要Attribute,你想要一个把T变成你可以排序的东西的函数。您有三个选择:

继续狂欢,列出你拥有的每一个可排序的概念。

public <T> Array<T> sortByInt(Array<T> input, ToIntFunction<T> f) {}
public <T> Array<T> sortByString(Array<T> input, Function<T, String> f) {}
public <T> Array<T> sortByDouble(Array<T> input, ToDoubleFunction<T, String> f) {}

等等。这些方法确实需要不同的名称,这里不要重载。

映射到反对和祈祷

您不知道如何对任何给定对象进行排序。您大概只知道如何对整数、双精度和字符串进行排序。你可以写:

public <T> Array<T> sortByDouble(Array<T> input, Function<T, ?> f) {}

然后在运行时检查函数是否映射到您想要的。如果函数映射到,比如说,InputStream,这显然不是你可以排序的东西,你必须检查它,然后抛出一个异常。如果一个对象映射到一个 int 而另一个对象映射到一个字符串,它也会变得相当混乱。这听起来很简单,但事实并非如此。不要这样做。

使用 java' 内置的自订概念。

Java 对此有一个类型:Comparable。这有点复杂。在这里,您希望对象可以与自己进行比较,所以:

public <T, V extends Comparable<V>> Array<T> sort(Array<T> input, Function<T, V> f) {}

这有点复杂,但它是最正确的版本。让我们来看看吧:

  • &lt;T, V... &gt; 部分:这表示此方法有 2 个类型变量。它们与普通变量一样,只是它们包含类型。
  • T:它没有任何界限。因此,它可以是任何东西。任何调用此方法的代码都将显式选择某些内容,或者编译器会找出答案。
  • V:这是有界限的。 V不能只是任何东西。 V 必须是某种类型,它具有它实现的属性Comparable&lt;V&gt; - 换句话说,一种可以将自己与自己类型的另一个值进行比较的东西。 StringInteger,还有很多其他java内置的东西都是这样的。 StringV 填写的有效类型。
  • Array&lt;T&gt; - 方法返回的内容。
  • sort - 方法名
  • Array&lt;T&gt; input - 输入。请注意,这与返回类型相关联。
  • Function&lt;T, V&gt; - 一个函数。这个函数将接收一个类型为 T 的对象并返回一个类型为 V 的对象。记住,V 不能只是任何东西——它需要是某种特定的类型,可以对自身与其他相同类型的东西进行排序,例如StringInteger

有了这些,你就可以编写一些代码了。例如:

T first = input.get(0); // still no idea what T is. But `input.get(0)` returns it.
T second = input.get(1);
V firstAttribute = function.apply(first); // extracts the sortable attribute
V secondAttribute = function.apply(second);
int ordering = firstAttribute.compareTo(secondAttribute); // magic!

最后一行是一个奇迹。它可以编译并保证可以工作:firstAttribute 是V,虽然我们不知道 V 是什么(可能是字符串。也可能是整数),但我们知道 V 有 int compareTo(V other) 方法。所以,我们可以调用它。负数表示firstsecond 之前,正数表示first 在第二个之后,0 响应表示firstsecond 要么相等,要么就比较它们而言,兄弟姐妹 - 两者都不是“之前”。

这个函数就是编写排序算法所需要的。

请注意,鉴于firstT,您可以这样写:

Array<T> output = new Array<T>();
output.add(first);

编译器不知道T是什么,但它知道first是一个T,所以这个调用是允许的。

【讨论】:

  • 不错的答案老兄
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-11
  • 1970-01-01
  • 1970-01-01
  • 2020-04-30
  • 2011-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多