Java 8 流将字符串映射到 MyObject

Java 8 Streams mapping String into MyObject

我有一个 List<String> tennisLines 包含几行关于网球比赛的信息,每行包含一场网球比赛的信息,比赛名称、地点、轮次、获胜者、失败者、日期等,由一个分隔分号.

每场比赛都有一个独特的名称,并包含多场网球比赛。 我创建了一个 TennisTournament class,其中包括锦标赛的名称、地点和相关的网球比赛 List<TennisMatch> 等。 class TennisMatch 包含获胜者、失败者和回合。

我正在尝试将列表 tennisLines 转换为 List<TennisTournament> tennisTournamentList 所以基本上将每一行转换为一个 TennisMatchs 实例并将每组网球比赛添加到网球比赛列表中最终创建一个 TennisTournament 对象。
我创建了一个流 Stream<String> streamLines,但我不知道如何将它们映射到包含另一个对象的对象中。

这是列表的摘录,最终应该是一个 TennisTournament 对象,它还包含一个大小为 27 的列表 List<TennisMatch>

location;tournament;match_date;series;court;surface;round;best_of;winner;loser;wrank;lrank;wpts;lpts;w1;l1;w2;l2;w3;l3;w4;l4;w5;l5;tourney_id
Lyon;Lyon Open;2019-05-19;ATP250;Outdoor;Clay;1st Round;3;Millman J.;Andujar P.;55;93;875;608;6;1;6;3;0;0;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-19;ATP250;Outdoor;Clay;1st Round;3;Tsonga J.W.;Lajovic D.;85;33;633;1316;7;6;6;4;0;0;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-20;ATP250;Outdoor;Clay;1st Round;3;Humbert U.;Norrie C.;61;41;823;1055;6;1;6;3;0;0;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-20;ATP250;Outdoor;Clay;1st Round;3;Johnson S.;Harris L.;59;89;850;617;6;2;7;6;0;0;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-20;ATP250;Outdoor;Clay;1st Round;3;Herbert P.H.;Chardy J.;42;40;1053;1065;6;2;7;5;0;0;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-20;ATP250;Outdoor;Clay;1st Round;3;Lamasine T.;Sinner J.;270;229;153;215;6;0;7;6;0;0;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-20;ATP250;Outdoor;Clay;1st Round;3;Diez S.;Tomic B.;262;82;165;665;6;4;4;1;0;0;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-20;ATP250;Outdoor;Clay;1st Round;3;Fritz T.;Vesely J.;46;105;1010;543;7;5;7;6;0;0;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-20;ATP250;Outdoor;Clay;1st Round;3;Gasquet R.;Janvier M.;39;199;1105;263;6;7;6;2;7;6;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-21;ATP250;Outdoor;Clay;1st Round;3;Moutet C.;Opelka R.;117;58;495;853;6;3;2;6;7;6;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-21;ATP250;Outdoor;Clay;1st Round;3;Cuevas P.;Hurkacz H.;50;43;963;1040;6;4;6;4;0;0;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-21;ATP250;Outdoor;Clay;1st Round;3;Paire B.;Mcdonald M.;51;65;938;796;3;6;7;6;6;1;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-21;ATP250;Outdoor;Clay;2nd Round;3;Johnson S.;Herbert P.H.;59;42;850;1053;7;6;5;7;6;1;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-21;ATP250;Outdoor;Clay;2nd Round;3;Auger-Aliassime F.;Millman J.;28;55;1344;875;7;6;7;5;0;0;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-22;ATP250;Outdoor;Clay;2nd Round;3;Paire B.;Cuevas P.;51;50;938;963;6;4;6;3;0;0;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-22;ATP250;Outdoor;Clay;2nd Round;3;Shapovalov D.;Humbert U.;23;61;1425;823;2;6;7;6;6;2;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-22;ATP250;Outdoor;Clay;2nd Round;3;Fritz T.;Gasquet R.;46;39;1010;1105;0;0;0;0;0;0;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-22;ATP250;Outdoor;Clay;2nd Round;3;Bautista Agut R.;Moutet C.;21;117;1690;495;4;6;6;4;6;3;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-22;ATP250;Outdoor;Clay;2nd Round;3;Tsonga J.W.;Diez S.;85;262;633;165;3;6;7;6;6;3;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-22;ATP250;Outdoor;Clay;2nd Round;3;Basilashvili N.;Lamasine T.;18;270;1925;153;7;5;7;5;0;0;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-23;ATP250;Outdoor;Clay;Quarterfinals;3;Fritz T.;Bautista Agut R.;46;21;1010;1690;6;7;6;3;6;4;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-23;ATP250;Outdoor;Clay;Quarterfinals;3;Paire B.;Shapovalov D.;51;23;938;1425;6;3;4;6;7;6;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-23;ATP250;Outdoor;Clay;Quarterfinals;3;Basilashvili N.;Tsonga J.W.;18;85;1925;633;6;4;6;4;0;0;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-23;ATP250;Outdoor;Clay;Quarterfinals;3;Auger-Aliassime F.;Johnson S.;28;59;1344;850;6;4;2;6;6;4;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-24;ATP250;Outdoor;Clay;Semifinals;3;Paire B.;Fritz T.;51;46;938;1010;6;4;6;2;0;0;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-24;ATP250;Outdoor;Clay;Semifinals;3;Auger-Aliassime F.;Basilashvili N.;28;18;1344;1925;2;6;7;6;6;4;0;0;0;0;2019-031
Lyon;Lyon Open;2019-05-25;ATP250;Outdoor;Clay;The Final;3;Paire B.;Auger-Aliassime F.;51;28;938;1344;6;4;6;3;0;0;0;0;0;0;2019-031

这里是网球锦标赛 classs

public class TennisTournament {
   private String location; 
   private String name;
   private String type;   
   private boolean outside = true;
   private String surface;       
   private LocalDate lastMatchDate;      
   private List<TennisMatch> matches = new ArrayList<>();
   // constructors, getters, setters, etc.

我已经成功制作了 TennisTournament 的列表,但没有使用流在其中进行匹配:

tennisLines.stream()
   .skip(1)
   .map(l -> { return l.split(SEPARATOR); }) 
   .forEach(c -> {
          if (c[ROUND_INDEX].equals(THE_FINAL)){
              TennisTournament tournament = 
                         new TennisTournament(c[LOCATION_INDEX], 
                         c[TOURNAMENT_INDEX], c[SERIES_INDEX],   
                         c[COURT_INDEX].equals(OUTDOOR), 
                         c[SURFACE_INDEX],   
                         LocalDate.parse(c[MATCH_DATE_INDEX]));
          }
          tennisTournamentList.add(tournament)
    });

假设一个数组包含这应该有效的所有行。您可能需要根据实际应用调整一些内容。

经过一番考虑后,我将其修改为使用循环而不是流,因为两个独立的数据结构 需要创建。它们都可以同时在一个循环中创建。 我相信它比我原来的答案更有效,当然也更紧凑。

引用特定数组元素的索引常量。他们还有助于文档。

static int WINNER = 8;
static int LOCATION = 0;
static int TOURNAMENT = 1;
static int DATE = 2;
static int COURT = 4;
static int SURFACE = 5;
static int LOSER = 9;
static int ROUND = 6;
  • 分配一个映射来存储 TennisMatch 个实例。关键是比赛的胜者
  • 分配一个列表来保存锦标赛获胜者的数据。
Map<String, List<TennisMatch>> matches = new HashMap<>();
List<TennisTournament> tournamentWinners = new ArrayList<>();
  • 遍历行,跳过第一行(第 header 列)
  • ; 分隔符上拆分行
  • 通过键入最后一轮为获胜者创建一个 TennisTournament 实例
  • 对于所有条目,创建获胜者(键)到获胜比赛列表(值)的映射。
    • 这使用 computeIfAbsent 方法创建和 return 一个列表(如果列表不存在)。
    • 否则,现有列表用于填充获胜的比赛。
for (int i = 1; i < lines.length; i++) {
    String[] arr = lines[i].split(";");
    if (arr[ROUND].equals("The Final")) {
        tournamentWinners.add(new TennisTournament(arr[LOCATION],
                arr[TOURNAMENT], arr[COURT], arr[SURFACE],
                arr[WINNER], arr[DATE]));
    }
    
    matches.computeIfAbsent(arr[WINNER],
            v -> new ArrayList<>())
            .add(new TennisMatch(arr[WINNER], arr[LOSER],
                    arr[ROUND]));
}   

现在为获胜的个人添加比赛是一件简单的事情 通过简单地从 TennisTournament 实例中获得锦标赛获胜者来获得锦标赛 并将其用作匹配映射的键。

for (TennisTournament tourney : tournamentWinners) {
    tourney.setMatches(matches.get(tourney.getWinner()));
}

显示结果(本例中只有一个)

tournamentWinners.forEach(tourney -> {
    System.out.println(tourney);
    for (TennisMatch m : tourney.getMatches()) {
        System.out.println("          " + m);
    }
});

打印

[Lyon, Lyon Open, Outdoor, Clay, 2019-05-25]
          [Paire B., Mcdonald M., 1st Round]
          [Paire B., Cuevas P., 2nd Round]
          [Paire B., Shapovalov D., Quarterfinals]
          [Paire B., Fritz T., Semifinals]
          [Paire B., Auger-Aliassime F., The Final]

这是类。为了减少 "clutter" 只有必要的 getter 和 setter 显示了此示例。

class TennisMatch {
    String winner;
    String loser;
    String round;
    
    public TennisMatch(String winner, String loser, String round) {
        this.winner = winner;
        this.loser = loser;
        this.round = round;
    }
    
    @Override
    public String toString() {
        return String.format("[%s, %s, %s]", winner, loser, round);
    }
}

class TennisTournament {
    String location;
    String series;
    String court;
    String surface;
    LocalDate date;
    String winner;
    List<TennisMatch> matches;
    
    public TennisTournament(String location, String series,
            String court, String surface, String winner,
            String stringDate) {
        this.location = location;
        this.series = series;
        this.court = court;
        this.surface = surface;
        this.winner = winner;
        this.date = LocalDate.parse(stringDate);
    }
    
    public List<TennisMatch> getMatches() {
        return matches;
    }
    
    public String getWinner() {
        return winner;
    }
    
    public void setMatches(List<TennisMatch> matches) {
        // defensive copy
        this.matches = new ArrayList<>(matches);
    }
    
    @Override
    public String toString() {
        return String.format("[%s, %s, %s, %s, %s]", location, series,
                court, surface, date);
    }
}