Java 8 Streams отображает строку в MyObject

avatar
William
8 августа 2021 в 17:08
57
1
1

У меня есть List<String> tennisLines, который содержит несколько строк о теннисных матчах, каждая строка содержит информацию об одном теннисном матче с названием турнира, местом проведения, раундом, победителем, проигравшим, датой и т. д., разделенными точкой с запятой.

Каждый турнир имеет уникальное название и содержит несколько теннисных матчей. Я создал класс TennisTournament, который включает название турнира, местонахождение и связанные с ним теннисные матчи List<TennisMatch> и т. д. Класс TennisMatch содержит победителя, проигравшего и раунд.

Я пытаюсь преобразовать список tennisLines в <98483334445161>, поэтому в основном превращаю каждую строку в экземпляр 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

Вот классы TennisTournament

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)
    });
Источник

Ответы (1)

avatar
WJS
22 января 2022 в 01:05
1

Предполагая, что массив содержит все строки, это должно работать. Возможно, вам потребуется настроить некоторые вещи для вашего реального приложения.

После некоторых размышлений я изменил это, чтобы использовать цикл, а не потоки, так как две независимые структуры данных нужно создать. Они оба могут быть созданы в одном цикле одновременно. Я считаю, что это более эффективно и, безусловно, более компактно, чем мой первоначальный ответ.

Константы индекса для ссылки на определенные элементы массива. Они также помогают в документации.

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<>();
  • Перебрать строки, пропуская первую (заголовок столбца)
  • разбить строки по разделителю ;
  • создать экземпляр TennisTournament для победителя, введя ключ в последнем раунде
  • для всех записей создать карту победителя (ключ) в список выигранных матчей (значение).
    • здесь используется метод computeIfAbsent для создания и возврата списка, если он отсутствует.
    • в противном случае существующий список используется для заполнения выигранных матчей.
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" только необходимые геттеры и сеттеры для показан этот пример.

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);
    }
}