Skip to content

Instantly share code, notes, and snippets.

@ayago
Last active May 17, 2023 05:12
Show Gist options
  • Save ayago/5281a57d4fb64b307fd115eadb6b907e to your computer and use it in GitHub Desktop.
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
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