Java 通过Index(索引)数组同时对多个数组进行排序

Java 中,可以通过索引数组(Index Array)来同时对多个数组进行排序。可以先构建一个索引数组,然后根据一个数组的排序顺序调整这个索引数组,接着使用该索引数组对其他数组进行同步排序。本文主要介绍Java同时对多个数组排序的三种方法。

示例代码

int[] indexes = new int[]{0,2,8,5};
String[] sources = new String[]{"how", "are", "today", "you"};
String[] targets = new String[]{"I", "am", "thanks", "fine"};

实现效果

indexes -> {0,2,5,8}
sources -> {"how", "are", "you", "today"}
targets -> {"I", "am", "fine", "thanks"}

根据indexes对这三个数组进行排序

1、使用比较器Comparator

通过使用 Comparator索引数组,可以对多个数组进行同步排序。索引数组用于存储排序的顺序,Comparator 则帮助我们根据某一个主数组的元素进行比较,然后应用排序后的索引来重新排列其他数组。

import java.io.*;
import java.util.*;
class Test {
public static String[] sortWithIndex (String[] strArr, 
int[] intIndex )
    {
     if (! isSorted(intIndex)){
        final List<String> stringList = Arrays.asList(strArr);
        Collections.sort(stringList, Comparator.comparing(
          s -> intIndex[stringList.indexOf(s)]));
        return stringList.toArray(new String[stringList.size()]);
       }
     else
        return strArr;
    }
public static boolean isSorted(int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        if (arr[i + 1] < arr[i]) {
            return false;
        };
    }
    return true;
}       

// Driver program to test function.
    public static void main(String args[])
    {
        int[] indexes = new int[]{0,2,8,5};
        String[] sources = new String[]{"how", "are", "today", "you"};
        String[] targets = new String[]{"I", "am", "thanks", "fine"};   
        String[] sortedSources = sortWithIndex(sources,indexes);
        String[] sortedTargets = sortWithIndex(targets,indexes);
        Arrays.sort(indexes);
        System.out.println("Sorted Sources " 
        + Arrays.toString(sortedSources) + " Sorted Targets " 
        + Arrays.toString(sortedTargets)  + " Sorted Indexes "
        + Arrays.toString(indexes));
    }
}

输出:

Sorted Sources [how, are, you, today] Sorted Targets [I, am, fine, thanks] Sorted Indexes [0, 2, 5, 8]

2、使用Lambda表达式

可以使用索引数组和 Lambda 表达式来同时对多个数组进行排序。生成一个索引数组,然后根据该索引数组的顺序对多个数组进行排序。

import java.io.*;
import java.util.*;
public class Test {
public static String[] sortWithIndex (String[] strArr, 
int[] intIndex )
    {
  if (! isSorted(intIndex)) {
        final List<String> stringList = Arrays.asList(strArr);
        Collections.sort(stringList, (left, right)
        -> intIndex[stringList.indexOf(left)] 
        - intIndex[stringList.indexOf(right)]);
        return stringList.toArray(new String[stringList.size()]);
  }
  else 
    return strArr;
    }
public static boolean isSorted(int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        if (arr[i + 1] < arr[i]) {
            return false;
        };
    }
    return true;
}  
// Driver program to test function.
public static void main(String args[])
{
    int[] indexes = new int[]{0,2,5,8};
    String[] sources = new String[]{"how", "are", "today", "you"};
    String[] targets = new String[]{"I", "am", "thanks", "fine"};   
    String[] sortedSources = sortWithIndex(sources,indexes);
    String[] sortedTargets = sortWithIndex(targets,indexes);
    Arrays.sort(indexes);
    System.out.println("Sorted Sources " 
    + Arrays.toString(sortedSources) + " Sorted Targets "
    + Arrays.toString(sortedTargets)  + " Sorted Indexes " 
    + Arrays.toString(indexes));
}

3、使用List和map实现

通过使用索引数组可以同时对多个数组进行排序。可以使用 ListMap 来帮助实现这个功能,特别是当需要根据一个主数组的排序顺序,来重新排列其他关联的数组时。

import java.util.*;
import java.lang.*;
import java.io.*;
public class Test{
    public static <T extends Comparable<T>> 
    void sortWithIndex( final List<T> key, List<?>... lists){
        if(key == null || lists == null)
            throw new NullPointerException("Key cannot be null.");
        for(List<?> list : lists)
            if(list.size() != key.size())
                throw new IllegalArgumentException(
                  "All lists should be of the same size");
        // 列表的大小为0或1,不需要排序
        if(key.size() < 2)
            return;
        // 创建索引列表
        List<Integer> indices = new ArrayList<Integer>();
        for(int i = 0; i < key.size(); i++)
            indices.add(i);
        // 根据键对索引列表进行排序
        Collections.sort(indices, new Comparator<Integer>(){
            @Override public int compare(Integer i, Integer j) {
                return key.get(i).compareTo(key.get(j));
            }
        });
        Map<Integer, Integer> swapMap = 
        new HashMap<Integer, Integer>(indices.size());
        List<Integer> swapFrom = 
        new ArrayList<Integer>(indices.size()),
         swapTo   = new ArrayList<Integer>(indices.size());
        // 创建允许按N个交换对列表排序的映射。
        for(int i = 0; i < key.size(); i++){
            int k = indices.get(i);
            while(i != k && swapMap.containsKey(k))
                k = swapMap.get(k);
            swapFrom.add(i);
            swapTo.add(k);
            swapMap.put(i, k);
        }
        // 使用交换顺序通过交换元素对每个列表进行排序
        for(List<?> list : lists)
            for(int i = 0; i < list.size(); i++)
                Collections.swap(list, swapFrom.get(i), 
                swapTo.get(i));
    }
    public static void main (String[] args) throws java.lang.Exception{
      List<Integer> index = Arrays.asList(0,2,8,5);
      List<String> sources =
      Arrays.asList("how", "are", "today", "you");
      // 列表类型不需要相同
      List<String> targets  = 
      Arrays.asList("I", "am", "thanks", "fine");
      sortWithIndex(index, index, sources, targets);
      System.out.println("Sorted Sources " 
      + sources + " Sorted Targets " 
      + targets  + " Sorted Indexes " + index);
    }
}

输出:

Sorted Sources [how, are, you, today] Sorted Targets [I, am, fine, thanks] Sorted Indexes [0, 2, 5, 8]

推荐阅读
cjavapy编程之路首页