Java 8 Streams mapping String into MyObject
Assuming that an array contains all the lines this should work. You will probably need to adjust some things for your actual application.
After some consideration I modified this to use a loop rather than streams since two independent data structures need to be created. They can both be created in a single loop at the same time. I believe it is more efficient and certainly more compact that my original answer.
Index constants to reference specific array elements. They also aid in documentation.
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;
- Allocate a map to store the
TennisMatch
instances. The key is the winner of the match - Allocate a list to hold the data for the tournament winners.
Map<String, List<TennisMatch>> matches = new HashMap<>();
List<TennisTournament> tournamentWinners = new ArrayList<>();
- Loop over the lines, skipping the first (column header)
- split the lines on the
;
delimiter - create a
TennisTournament
instance for a the winner by keying on the final round - for all the entries, create a map of winner (key) to list of won matches (value).
- this uses the computeIfAbsent method to create and return a list if one isn't present.
- other wise, the existing list is used to populate the won matches.
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]));
}
Now it is a simple matter to add the matches to for the individual who won the tournament by simply getting the tournament winner from the TennisTournament instance and using that as a key into the map of matches.
for (TennisTournament tourney : tournamentWinners) {
tourney.setMatches(matches.get(tourney.getWinner()));
}
Display the results (in this case only one)
tournamentWinners.forEach(tourney -> {
System.out.println(tourney);
for (TennisMatch m : tourney.getMatches()) {
System.out.println(" " + m);
}
});
prints
[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]
Here are the classes. To keep down the "clutter"
only essential getters and setters for
this example are shown.
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);
}
}