Skip to content

Instantly share code, notes, and snippets.

@visakha
Last active April 26, 2018 13:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save visakha/8ac7f823e02192beb23a3f869fc4a196 to your computer and use it in GitHub Desktop.
Save visakha/8ac7f823e02192beb23a3f869fc4a196 to your computer and use it in GitHub Desktop.
Java 8 streams : How to surface the comparator winning rule to the domain object
/**
* We have a list of cars identified by Make,
* other attributes are name, rating, mileage
* The idea is to pick 1 car from each make by applying the below rules in sequence
*
* Rule 1 : if there is only one car per make: then mark it for Pick: pick = 'onlyOneItem'
* Rule 2 : if not Rule 1 then Pick the car with better rating: pick = 'higerRating'
* Rule 3 : if not Rule 2 then Pick the car with least mileage: pick= 'lowerMileage'
*
* acceptence criteria: Rules are to be applied in order and if one rule applies then the rest can be skipped
*/
val _none = "none"
val _onlyOneItem = "onlyOneItem";
val _higherRating = "higherRating";
val _lowerMiles = "lowerMiles"
data class Car(val make: String, val name: String, val rating: Int, val mileage: Int, var reason4pick: String = "none", val expectedReason: String = "none"){
fun negMileage() = mileage * -1
}
val cars = listOf<Car>(
Car("Honda", "AnaKat's new SUV", 5, 2000, expectedReason = _higherRating)
, Car("Honda", "AnaKat's sedan", 3, 3000)
// ------------// ------------// ------------// ------------// ------------// ------------
, Car("Toyota", "AnaKat's HighLander", 5, 1000, expectedReason = _lowerMiles)
, Car("Toyota", "AnaKat's 4 runner", 5, 2000)
, Car("Toyota", "AnaKat's Camry", 3, 100)
// ------------// ------------// ------------// ------------// ------------// ------------
, Car("Mazda", "Ravi's SUV", 1, 7000, expectedReason = _onlyOneItem)
// ------------// ------------// ------------// ------------// ------------// ------------
, Car("Nissan", "Kondal's Nissan Van", 5, 2000, expectedReason = _onlyOneItem)
// ------------// ------------// ------------// ------------// ------------// ------------
, Car("LandRover", "Jims old LandRV", 4, 1000)
, Car("LandRover", "Jims crusr", 5, 1000, expectedReason = _higherRating)
// ------------// ------------// ------------// ------------// ------------// ------------
)
@Test
fun strmGroupByMarkPrimary() {
fun applyRules(vl: List<Car>): List<Car> {
if (vl.size == 1) {vl.get(0).reason4pick = _onlyOneItem; return vl} // ----> marker 1
val maxRatingOrLowerMileageCar = vl.stream()
.max ( Comparator.comparingInt(Car::rating)
.thenComparingInt(Car::negMileage)).get()
// How to update the reason for pick just like we it 5 lines above (marker 1) ???
return listOf(maxRatingOrLowerMileageCar)
}
val grpdBy: MutableMap<String, MutableList<Car>> = cars.stream().collect(Collectors.groupingBy({ e -> e.make }, Collectors.toList<Car>()))
val f1 = grpdBy.flatMap { (k, vl) -> applyRules(vl) }
f1.forEach { assertEquals(it.reason4pick, it.expectedReason) }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment