Last active
May 17, 2023 05:12
-
-
Save ayago/5281a57d4fb64b307fd115eadb6b907e to your computer and use it in GitHub Desktop.
Java Demonstration on how to perform map reduce from a file to create an aggregation/report
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.IOException; | |
import java.nio.file.Files; | |
import java.nio.file.Paths; | |
import java.util.Objects; | |
import java.util.Scanner; | |
import java.util.stream.Stream; | |
public class GameDataService{ | |
private final GameDataRepository gameDataRepository; | |
GameDataService(GameDataRepository gameDataRepository){ | |
this.gameDataRepository = gameDataRepository; | |
} | |
public static void main(String[] args){ | |
GameDataRepository gameDataRepository = new FileBasedGameDataRepository(args[0]); | |
GameDataService gameDataService = new GameDataService(gameDataRepository); | |
System.out.print("Specify Team name: "); | |
Scanner scanner = new Scanner(System.in); | |
String teamOfInterest = scanner.nextLine(); | |
TeamStatistics teamStatistics = gameDataService.getTeamStatistics(teamOfInterest); | |
String display = String.format( | |
"Team %s - games: %d, wins: %d, losses: %d", | |
teamStatistics.teamName, | |
teamStatistics.numberOfGames, | |
teamStatistics.numberOfWins, | |
teamStatistics.numberOfLosses | |
); | |
System.out.println(display); | |
} | |
private TeamStatistics getTeamStatistics(String teamName){ | |
return gameDataRepository.getGameDataRelevantToTeam( | |
Objects.requireNonNull(teamName, "Team name must not be null")) | |
.reduce( | |
TeamStatistics.createStatistics(teamName), | |
TeamStatistics::processGameData, | |
(previousStat, currentStat) -> currentStat | |
); | |
} | |
} | |
interface GameDataRepository { | |
Stream<GameData> getGameDataRelevantToTeam(String teamName); | |
} | |
class FileBasedGameDataRepository implements GameDataRepository{ | |
private final String fileName; | |
FileBasedGameDataRepository(String fileName){ | |
this.fileName = fileName; | |
} | |
@Override | |
public Stream<GameData> getGameDataRelevantToTeam(String teamName){ | |
try{ | |
return Files.lines(Paths.get(fileName)) | |
.map(line -> line.split(",")) | |
.filter(parts -> teamName.equals(parts[0]) || teamName.equals(parts[1])) | |
.map(parts -> GameData.builder() | |
.setHomeTeam(parts[0].trim()) | |
.setAwayTeam(parts[1].trim()) | |
.setHomeTeamScore(Integer.parseInt(parts[2].trim())) | |
.setAwayTeamScore(Integer.parseInt(parts[3].trim())) | |
.build() | |
); | |
} catch (IOException e) { | |
throw new RuntimeException(e); | |
} | |
} | |
} | |
class GameData { | |
final String homeTeam; | |
final String awayTeam; | |
final int homeTeamScore; | |
final int awayTeamScore; | |
private GameData(String homeTeam, String awayTeam, int homeTeamScore, int awayTeamScore){ | |
this.homeTeam = homeTeam; | |
this.awayTeam = awayTeam; | |
this.homeTeamScore = homeTeamScore; | |
this.awayTeamScore = awayTeamScore; | |
} | |
static GameDataBuilder builder(){ | |
return new GameDataBuilder(); | |
} | |
static class GameDataBuilder { | |
private String homeTeam; | |
private String awayTeam; | |
private int homeTeamScore; | |
private int awayTeamScore; | |
private GameDataBuilder(){} | |
GameDataBuilder setHomeTeam(String homeTeam){ | |
this.homeTeam = homeTeam; | |
return this; | |
} | |
GameDataBuilder setAwayTeam(String awayTeam){ | |
this.awayTeam = awayTeam; | |
return this; | |
} | |
GameDataBuilder setHomeTeamScore(int homeTeamScore){ | |
this.homeTeamScore = homeTeamScore; | |
return this; | |
} | |
GameDataBuilder setAwayTeamScore(int awayTeamScore){ | |
this.awayTeamScore = awayTeamScore; | |
return this; | |
} | |
GameData build(){ | |
return new GameData(homeTeam, awayTeam, homeTeamScore, awayTeamScore); | |
} | |
} | |
} | |
class TeamStatistics { | |
private static final int STARTING_COUNT = 0; | |
final String teamName; | |
final int numberOfGames; | |
final int numberOfWins; | |
final int numberOfLosses; | |
static TeamStatistics createStatistics(String teamName){ | |
return new TeamStatistics(Objects.requireNonNull(teamName), STARTING_COUNT, STARTING_COUNT, STARTING_COUNT); | |
} | |
private TeamStatistics(String teamName, int numberOfGames, int numberOfWins, int numberOfLosses){ | |
this.teamName = teamName; | |
this.numberOfGames = numberOfGames; | |
this.numberOfWins = numberOfWins; | |
this.numberOfLosses = numberOfLosses; | |
} | |
TeamStatistics processGameData(GameData gameData){ | |
if(teamName.equals(gameData.homeTeam)) { | |
return updateTeamStats(gameData.homeTeamScore, gameData.awayTeamScore); | |
} else if(teamName.equals(gameData.awayTeam)) { | |
return updateTeamStats(gameData.awayTeamScore, gameData.homeTeamScore); | |
} | |
return this; | |
} | |
private TeamStatistics updateTeamStats(int thisTeamScore, int otherTeamScore){ | |
int updatedNumberOfGames = numberOfGames + 1; | |
if(thisTeamScore < otherTeamScore){ | |
return new TeamStatistics(teamName, updatedNumberOfGames, numberOfWins, numberOfLosses + 1); | |
} else if(thisTeamScore > otherTeamScore) { | |
return new TeamStatistics(teamName, updatedNumberOfGames, numberOfWins + 1, numberOfLosses); | |
} else { | |
return new TeamStatistics(teamName, updatedNumberOfGames, numberOfWins, numberOfLosses); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment