Java:如何对两个相应的数组进行排序?

时间:2015-12-07 02:57:51

标签: java arrays

我有两个数组:

First array:
25, 20, 50, 30, 12, 11...

Second Array: 
New York, New Jersey, Detroit, Atlanta, Chicago, Los Angeles

第二个数组中的每两个城市对应于第一个数据中的一个值。

示例:纽约和新泽西将对应25,底特律和亚特兰大将对应20,依此类推。

我想按降序(50,30,25,20 ......)重新排序第一个数组的数字,但我还希望第二个数组的城市相应地移动,以便它们之前具有相同的值排序之后。

我如何完成这项任务? (我可以使用ArrayList或Array,无论哪个更简单)

4 个答案:

答案 0 :(得分:1)

您可以使用TreeMap:

Map<Integer, String[]> map = new TreeMap<>();
for(int i=0;i<firstArray.length;i++){
   map.put(firstArray[i], new String[]{secondArray[i * 2], secondArray[i*2+1]});
}

此地图将按自然顺序排序。

但我建议你做容器类。类似的东西:

public class CityPair{
  public int value;
  public String[] cities = new String[2]; 
}

现在您可以按数据填写列表:

...   
ArrayList list = new ArrayList<CityPair>();

for(int i=0; i<firstArray.length; i++){
  CityPair pair = new CityPair();
  pair.value = firstArray[i];
  pair.cities[0] = secondArray[i*2];
  pair.cities[1] = secondArray[i*2+1];
  list.add(pair);
}
...

如您所见,我没有检查索引是否超出范围&#34;但您应该这样做。之后,您可以对列表进行排序。您可以使用例如Bubble sort算法手动执行此操作,但更好的方法是编写自定义比较器:

public class CityPairComparator implements Comparator<CityPair> {
    @Override
    public int compare(CityPair pair1, CityPair pair2) {
        return Integer.compare(pair1.value, pair2.value);
    }
}

现在,您可以使用Collections实用程序类对列表进行排序:

Collections.sort(list, new CityPairComparator());

使用此approch,您可以替换String[] citiesCityPair中的ArrayList<Sting> cities。然后,它可以为每个值添加两个以上的城市。

答案 1 :(得分:0)

这是一个(4行)解决方案,它也处理不匹配的数组长度:

int[] numbers = {25, 20, 50};
String[] cities = {"New York", "New Jersey", "Detroit", "Atlanta", "Chicago", "Los Angeles"};

Map<Object, Object> map = new TreeMap<>(Comparator.comparing(Integer.class::cast, Integer::compare).reversed());
for (Iterator<?> n = Arrays.stream(numbers).iterator(),
    s = Arrays.stream(String.join(",", cities).split(",(?=(([^,]*,){2})*[^,]*,[^,]*$)")).iterator();
    n.hasNext() && s.hasNext(); )
    map.put(n.next(), s.next());
numbers = map.keySet().stream().map(String::valueOf).mapToInt(Integer::parseInt).toArray();
cities = map.values().stream().map(String::valueOf).map(s -> s.split(",")).flatMap(Arrays::stream).toArray(String[]::new);

这将从每个数组的流中动态创建两个迭代器,两者都键入Object以允许for循环内的双初始化。 cities数组首先连接成一个字符串,然后拆分成pair-as-a-String(使用适当的正则表达式)。两个迭代器的元素都填充TreeMap,它有一个反向的Integer比较器。

由于TreeMaps排序顺序进行迭代,因此可以使用keySet()values()的流来生成结果数组。

for循环的终端条件检查两个迭代器以查看是否有可用的下一个元素,如果数组的长度不相等,则会导致忽略较长数组的多余元素。

答案 2 :(得分:0)

我尝试过这样的解决方案,根据您的要求使用Arraylist:

首先,我为您的操作创建了一个新的数据结构。由于每个值将包含两个城市名称:

 public class Citizen implements Comparable<Citizen>  {

    private int citizenId;
    private String subjectOne;
    private String subjectTwo;


    public Citizen(int rollNumber, String subjectOne, String subjectTwo){
        this.citizenId = rollNumber;
        this.subjectOne = subjectOne;
        this.subjectTwo = subjectTwo;
    }

    public int getRollNumber() {
        return citizenId;
    }
    public void setRollNumber(int rollNumber) {
        this.citizenId = rollNumber;
    }
    public String getSubjectOne() {
        return subjectOne;
    }
    public void setSubjectOne(String subjectOne) {
        this.subjectOne = subjectOne;
    }
    public String getSubjectTwo() {
        return subjectTwo;
    }
    public void setSubjectTwo(String subjectTwo) {
        this.subjectTwo = subjectTwo;
    }


        public int compareTo(Citizen comparestu) {
            int compareage=((Citizen)comparestu).getRollNumber();
            /* For Ascending order*/
            return this.citizenId-compareage;

            /* For Descending order do like this */
            //return compareage-this.studentage;
        }

        @Override
        public String toString() {
            return "[ rollno=" + citizenId + ", subjectOne=" + subjectOne + ", subjectTwo=" + subjectTwo + "]";
        }   
}

正如您在此处所见,使用Comparable接口的实现将用于比较的参数视为citizenID。

现在致电:

public static void main(String[] args) {

        ArrayList<Citizen> studentList = new ArrayList<Citizen>();

        studentList.add(new Citizen(25, "New York", "New Jersey"));
        studentList.add(new Citizen(20, "Detroit", "Atlanta"));
        studentList.add(new Citizen(50, "Chicago", "Los Angeles"));
        studentList.add(new Citizen(30, "Kolkata", "Delhi"));
        studentList.add(new Citizen(12, "Munmbai", "Baranasi"));
        studentList.add(new Citizen(11, "Bangalore", "Goa"));



        Collections.sort(studentList);
           for(Citizen student: studentList){
                System.out.println(student);
           }
    }

输出:

[ rollno=11, subjectOne=Bangalore, subjectTwo=Goa]
[ rollno=12, subjectOne=Munmbai, subjectTwo=Baranasi]
[ rollno=20, subjectOne=Detroit, subjectTwo=Atlanta]
[ rollno=25, subjectOne=New York, subjectTwo=New Jersey]
[ rollno=30, subjectOne=Kolkata, subjectTwo=Delhi]
[ rollno=50, subjectOne=Chicago, subjectTwo=Los Angeles]

答案 3 :(得分:0)

Java 8提供了一种更优雅的方式,无需单独的映射即可完成此操作:

int[] array1;
String[] array2;

array2 = IntStream.range(0, Math.min(array1, array2))
    .boxed().sorted(Comparator.comparingInt(i -> array1[i]))
    .map(i -> array2[i])
    .toArray(array2);

仅需要装箱,因为IntStream没有自定义sorted的{​​{1}}方法。我不确定为什么不。

如果您希望以Comparator结尾,请使用List代替.collect(Collectors.toList())