如何按2个字段对对象进行排序Java

问题描述

我要读取的文件如下:

1995     Pokemon    Ikue Ôtani  
1940     Tom and Jerry    William Hanna 
1995     Pokemon    voice actor2
1940     Tom and Jerry    voice actor3
2000     Cartoon      voice actor

它大约有2万行。我已经可以读取文件并将数据存储在对象中。

        in = new BufferedReader(new FileReader(cartoonsFile));
            
        ArrayList<String> voiceActors = new ArrayList<>();  
        ArrayList<Cartoon> cartoons = new ArrayList<>();    
        
        //read each line
        String line = in.readLine();
        while (line != null) {
            String[] columns = line.split("\\t");
            String year = columns[0];
            String cartoon = columns[1];
            String voiceActor = columns[2];

            //make new object and store data

            Cartoon c = new Cartoon(Integer.parseInt(columns[0]),columns[1],columns[2]));
            cartoons.add(c); //add to the array list

对象

public class Cartoon {
  private int year;
  private String title;
  private String voiceActor;

  public Cartoon(int year,String title,String voiceActor) {
    this.year = year;
    this.title = title;
    this.voiceActor = voiceActor;
  }
};

我想在线程中读取文件并按年份排序。谁能提供示例代码说明如何一起实现多线程和合并排序?

我想要获得的输出

1940     Tom and Jerry         William Hanna 
                               voice actor2
                               voice actor3
                               voice actor4
                               voice actor5

1995     Pokemon               Ikue Ôtani  
                               voice actor2

         A Cartoon             voice actor1
                               voice actor2
                               voice actor3

2000     Cartoon               voice actor

解决方法

尝试一下。

List<CartoonYear> readAndSortByYear(String inFile) throws IOException {
    return Files.readAllLines(Paths.get(inFile))
        .parallelStream()
        .map(line -> line.split("\\t"))
        .map(columns -> new CartoonYear(Integer.parseInt(columns[0]),columns[1],columns[2]))
        .sorted(Comparator.comparing(CartoonYear::getYear))
        .collect(Collectors.toList());
}
,

处理您的数据结构(只是将其从相当特殊的CartoonYear重命名为Cartoon),并坚持使用@ saka1029使用Java流的好方法(而不是手动实现合并)排序算法),您可以执行以下操作:

package org.acme;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Cartoon {
  private int year;
  private String title;
  private String voiceActor;

  public Cartoon(int year,String title,String voiceActor) {
    this.year = year;
    this.title = title;
    this.voiceActor = voiceActor;
  }

  public static Map<String,List<Cartoon>> readAndGroupByYearAndTitle(String inFile) throws IOException {
    return Files.readAllLines(Paths.get(inFile))
      .parallelStream()
      .map(line -> line.split("\\t"))
      .map(columns -> new Cartoon(Integer.parseInt(columns[0]),columns[2]))
      .collect(Collectors.groupingBy(cartoon -> String.format("%4d %s",cartoon.year,cartoon.title)));
  }

  public static void main(String[] args) throws IOException {
    Map<String,List<Cartoon>> cartoonsGrouped = readAndGroupByYearAndTitle(args[0]);
    cartoonsGrouped.keySet()
      .parallelStream()
      .sorted()
      .forEachOrdered(group -> {
        boolean firstElement = true;
        for (Cartoon cartoonYear : cartoonsGrouped.get(group)) {
          if (firstElement) {
            System.out.printf("%4d  %-25s  %s%n",cartoonYear.year,cartoonYear.title,cartoonYear.voiceActor);
            firstElement = false;
          }
          else
            System.out.printf("%4s  %-25s  %s%n","",cartoonYear.voiceActor);
        }
      });
  }
}

这只是快速又肮脏,不是我引以为豪的代码。您每组仅打印年份和标题一次的要求也不会使代码与if-else更好。但是,假设您有一个这样的输入文件:

1995    Pokemon Ikue Ôtani
1940    Tom and Jerry   William Hanna
11  Sample  foo
1995    Pokemon voice actor2
1940    Tom and Jerry   voice actor3
2000    Cartoon voice actor
11  Sample  bar

您将获得如下输出:

  11  Sample                     foo
                                 bar
1940  Tom and Jerry              William Hanna
                                 voice actor3
1995  Pokemon                    Ikue Ôtani
                                 voice actor2
2000  Cartoon                    voice actor