Java:使用indexOf方法对基于另一个数组的数组进行排序

时间:2018-11-29 09:56:45

标签: java algorithm sorting lambda comparator

我想根据另一个数组(索引)的排序顺序遍历两个数组(A,B),在这种情况下为10、34、32、21。

String[] A: a, b, c, d
String[] B: e, f, g, h
int[] indexes: 10, 34, 32, 21
  

在这里为不好的例子道歉。我已经更新了索引数组以消除混乱。

预期的输入和输出

输入是三个数组。我想使用索引数组的排序遍历A,B。即我想找到一种方法来使用顺序(a,d,c,b)迭代A并使用顺序(e,h,g,f)来迭代B

我的方法:

我用一种我认为与另一种方法相同的解决方案解决了这个问题。但是,第二种方法不起作用。如果有人可以解释为什么它不起作用,我将不胜感激,因为我认为这可以使我更好地理解Collections.sort在Java中的工作方式。

List<Integer> indexOrder = new ArrayList<>(indexes.length);

for (int i = 0; i < indexes.length; i++) {
    indexOrder.add(i);
}

Collections.sort(indexOrder, Comparator.comparing((Integer s) -> indexes[s]));

this thread的启发,我创建了一个值(1、2、3 ... indexes.length)的ArrayList(首选AList而不是数组),然后使用带有ref的比较器对其进行排序。索引。 以上代码按预期工作。

但是,如果我将最后一行末尾的 indexs(s)更改为 indexes [indexOrder.indexOf(s)] 。排序将给出错误的结果。如果ArrayList的索引与其值相同,为什么indexOf(s)的结果不同于s。

Collections.sort(indexOrder, Comparator.comparing((Integer s) -> indexes[indexOrder.indexOf(s)]));

3 个答案:

答案 0 :(得分:6)

您似乎希望indexOrder.indexOf(s)始终等于s(因为您的List初始化为[0, 1, 2, 3],其中s的索引为{ {1}})。

虽然在原始s indexOrder中是正确的,但是当List开始交换Collections.sort的元素时,可能不再正确。

为了在排序时不依赖List的顺序,可以创建该indexOrder的副本:

List

答案 1 :(得分:3)

由于存储在索引中的最大值不会超过1000,所以我认为这种排序算法(这是计数排序的变体)的实现将是最佳选择。

final String[] A = { "a", "b", "c", "d" };
final String[] B = { "e", "f", "g", "h" };
final int[] indexes =  { 10, 34, 32, 21 };

// find out the max value in the array.
// The loop can be skipped with maxIndexValue = 1000; but i would most likely save some memory using the loop.
// Can also be replaced with : IntStream.of(indexes).max().getAsInt(), with such a small set of data it won't hurt performance that bad
int maxIndexValue = 0;
for (int indexValue: indexes) {
    if (maxIndexValue < indexValue) {
        maxIndexValue = indexValue;
    }
}
maxIndexValue += 1;

final String[] indexSortedA = new String[maxIndexValue];
final String[] indexSortedB = new String[maxIndexValue];
System.out.println(maxIndexValue);
// each value of A (and B) will be put at indexes position, it will result in a appropriately sorted arrays but with a lot of whitespace.
for (int i = 0; i < indexes.length; ++i) {
    indexSortedA[indexes[i]] = A[i];
    indexSortedB[indexes[i]] = B[i];
}

// Create final arrays by filtering empty values
final String[] sortedA = Arrays.stream(indexSortedA).filter(v -> v != null && !"".equals(v)).toArray(String[]::new);
final String[] sortedB = Arrays.stream(indexSortedB).filter(v -> v != null && !"".equals(v)).toArray(String[]::new);

此算法的复杂度将为:O(n)+ O(1000)+ O(2n)。它将比任何Collection.sort()都要好,但是会花费更多的内存。

答案 2 :(得分:0)

我试图同时运行两个代码,并且在两种情况下都得到相同的结果。

案例1:

public static void main(String[] args) {
    String[] A = { "a", "b", "c", "d" };
    String[] B = { "e", "f", "g", "h" };
    int[] indexes = { 0, 4, 2, 1 };

    List<Integer> indexOrder = new ArrayList<>(indexes.length);

    for (int i = 0; i < indexes.length; i++) {
        indexOrder.add(i);
        System.out.println(i);
    }

    //Collections.sort(indexOrder, Comparator.comparing((Integer s) -> indexes[s]));
    Collections.sort(indexOrder, Comparator.comparing((Integer s) -> indexes[indexOrder.indexOf(s)]));

    System.out.println(indexOrder.toString());
}

输出: 0 1个 2 3

[0,3,2,1]

情况2:

public static void main(String[] args) {
    String[] A = { "a", "b", "c", "d" };
    String[] B = { "e", "f", "g", "h" };
    int[] indexes = { 0, 4, 2, 1 };

    List<Integer> indexOrder = new ArrayList<>(indexes.length);

    for (int i = 0; i < indexes.length; i++) {
        indexOrder.add(i);
        System.out.println(i);
    }

    Collections.sort(indexOrder, Comparator.comparing((Integer s) -> indexes[s]));
    //Collections.sort(indexOrder, Comparator.comparing((Integer s) -> indexes[indexOrder.indexOf(s)]));

    System.out.println(indexOrder.toString());
}

输出: 0 1个 2 3

[0,3,2,1]