-
-
Save vivekragunathan/c2a0f5b07b9a17ea89d5b75ce5176fa1 to your computer and use it in GitHub Desktop.
A sample program demonstrating how JINQ is expressive and succinct.
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 jinq.core.Enumerable; | |
import jodash.Iterables; | |
import java.util.*; | |
/** | |
* A sample program, derived from real-time code, demonstrating how JINQ is expressive and succinct. | |
* | |
* While the MundaneCalculator.calculateCostsByDept might appear short (or not too long to read), lot of details | |
* and relevance to real-time code has been purposely stripped particularly to demonstrate the difference. In | |
* real time, MundaneXXXX like class/method has so much that it is difficult for the reader to stay in context. | |
* | |
* JINQ (JinqCalculator.calculateCostsByDept) is simple expressive and succinct, and helps organize rest of | |
* the code that feeds the JINQ pipeline | |
* | |
**/ | |
public class Jinqle { | |
private static class Employee implements Comparable<Employee> { | |
public final int id; | |
public final String name; | |
public final String department; | |
public final boolean intern; | |
public int hikePercent; | |
public int hikeAmount; | |
public Employee(int id, | |
String name, | |
String dept, | |
boolean intern) { | |
this.id = id; | |
this.name = name; | |
this.department = dept; | |
this.intern = intern; | |
} | |
@Override | |
public String toString() { | |
return String.format( | |
"(%s-%s) %s %s (%s, %s)", | |
intern ? "I" : "E", | |
id, | |
name, | |
department, | |
hikeAmount, | |
hikePercent | |
); | |
} | |
@Override | |
public int compareTo(Employee other) { | |
return this.name.compareTo(other.name); | |
} | |
} | |
private static class CostInfo { | |
public final String department; | |
private int hikePercent; | |
private int hikeAmount; | |
private int count = 1; | |
public CostInfo(Employee employee) { | |
this.department = employee.department; | |
this.hikeAmount = employee.hikeAmount; | |
this.hikePercent = employee.hikePercent; | |
} | |
public CostInfo(String dept, | |
int hikePercent, | |
int hikeAmount) { | |
this.department = dept; | |
this.hikePercent = hikePercent; | |
this.hikeAmount = hikeAmount; | |
} | |
public int update(int hikeAmount, int hikePercent) { | |
this.hikeAmount += hikeAmount; | |
this.hikePercent += hikePercent; | |
this.count++; | |
return count; | |
} | |
@Override | |
public String toString() { | |
return String.format( | |
"%s (%d): %s, %s", | |
department, | |
count, | |
hikeAmount, | |
hikePercent | |
); | |
} | |
public int getTotalHike() { | |
return this.hikeAmount; | |
} | |
public int getAverageHikePercent() { | |
return this.hikePercent / this.count; | |
} | |
} | |
public static final String[] departments = { | |
"System and Infrastructure", | |
"Application", | |
"Big Data", | |
"Operations", | |
"Production Support", | |
"Database", | |
"UX" | |
}; | |
public static List<Employee> employees() { | |
final List<Employee> employees = new ArrayList<>(); | |
final Random random = new Random(3333); | |
for (int index = 0; index < 100; ++index) { | |
final int id = index + 1; | |
final String name = "Name" + id; | |
final int deptIndex = random.nextInt(departments.length); | |
final String dept = departments[ deptIndex % departments.length ]; | |
final Employee emp = new Employee(id, name, dept, index % 2 == 0); | |
emp.hikeAmount = random.nextInt(5000); | |
emp.hikePercent = random.nextInt(10); | |
employees.add(emp); | |
} | |
return employees; | |
} | |
interface CostCalculator { | |
Map<String, CostInfo> calculateCostsByDept(); | |
} | |
static class JinqCalculator implements CostCalculator { | |
public final Iterable<Employee> employees; | |
public JinqCalculator(Iterable<Employee> employees) { | |
this.employees = employees; | |
} | |
@Override | |
public Map<String, CostInfo> calculateCostsByDept() { | |
return new Enumerable<>(employees) | |
.where(e -> !e.intern) | |
.select(CostInfo::new) | |
.toMap( | |
c -> c.department, | |
(m, v, c) -> v.update(c.hikeAmount, c.hikePercent) | |
); | |
} | |
} | |
static class MundaneCalculator implements CostCalculator { | |
private final Iterable<Employee> employees; | |
public MundaneCalculator(Iterable<Employee> employees) { | |
this.employees = employees; | |
} | |
@Override | |
public Map<String, CostInfo> calculateCostsByDept() { | |
final Map<String, CostInfo> costMap = new HashMap<>(); | |
for (Employee employee : employees) { | |
if (!employee.intern) { | |
continue; | |
} | |
CostInfo costInfo = costMap.get(employee.department); | |
if (costInfo == null) { | |
costInfo = new CostInfo( | |
employee.department, | |
employee.hikePercent, | |
employee.hikeAmount | |
); | |
costMap.put(employee.department, costInfo); | |
continue; | |
} | |
costInfo.update(employee.hikeAmount, employee.hikePercent); | |
} | |
return costMap; | |
} | |
} | |
public static void main(String[] args) { | |
final List<Employee> employees = employees(); | |
System.out.printf("Employees:%n%n%s%n", employees); | |
//final CostCalculator calculator = new MundaneCalculator(employees); | |
final CostCalculator calculator = new JinqCalculator(employees); | |
final Map<String, CostInfo> costs = calculator.calculateCostsByDept(); | |
final String log = Iterables.toString(costs.values(), "\n"); | |
System.out.printf("Cost Info:%n%n%s%n", log); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment