我的用例是我有餐馆对象的列表,其中包含属性作为城市,类型,评级,我想按照给定组合(城市,类型)的最高评级打印列表。当我创建这个示例来混淆java流时,请回复如何使用流来实现:
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.Map;
import java.util.Optional;
import static java.util.stream.Collectors.maxBy;
import static java.util.stream.Collectors.groupingBy;
import static java.util.Comparator.comparingLong;
class Restaurant {
public String city; // Any city
public String type; // Tier1, Tier2, etc.
public Long rating; // for simplicity sake, assume its a number from 1 to 5
public Restaurant(String city, String type, Long rating) {
this.city = city;
this.type = type;
this.rating = rating;
}
public String getCity() { return city; }
public String getType() { return type; }
public Long getRating() { return rating; }
}
public class HelloWorld
{
public static void main(String[] args)
{
List<Restaurant> mylist = new ArrayList<Restaurant>();
mylist.add(new Restaurant("City1", "Tier1", 1L));
mylist.add(new Restaurant("City1", "Tier1", 2L));
mylist.add(new Restaurant("City1", "Tier2", 1L));
mylist.add(new Restaurant("City2", "Tier1", 1L));
mylist.add(new Restaurant("City2", "Tier1", 3L));
mylist.add(new Restaurant("City2", "Tier3", 1L));
// expected outcome: (City1, Tier1, 2), (City1, Tier2, 1), (City2, Tier1, 3), (City2, Tier3, 1)
Map<String, Map<String, Optional<Restaurant>>> mymap =
mylist.stream().collect(groupingBy(Restaurant::getCity, groupingBy(Restaurant::getType, maxBy(comparingLong(Restaurant::getRating)))));
/* Upto here everything is fine, but I want to have everything stored back into a list. Tried flatMap(Map::values).collect(Collectors.toList()); but it fails*/
/*My output list should have 4 objects of Restaurant*/
/*(City1, Tier1, 2), (City1, Tier2, 1), (City2, Tier1, 3), (City2, Tier3, 1)*/
}
}
答案 0 :(得分:3)
首先,您可以创建复合键以摆脱嵌套映射。 Arrays.asList(r.getCity(), r.getType())
就是您所需要的。接下来,groupingBy
不适合你的情况,因为你应该处理那些讨厌的选项。而是使用toMap
收集器和自定义合并功能:
Map<List<String>, Restaurant> mymap = mylist.stream().collect(
toMap(r -> Arrays.asList(r.getCity(), r.getType()), r -> r,
BinaryOperator.maxBy(comparingLong(Restaurant::getRating))));
现在mymap.values()
是您想要的餐厅的平面集合。如果您真的想要List
,可以将其转储为一个:
List<Restaurant> list = new ArrayList<>(mymap.values());
答案 1 :(得分:-1)
我还没有使用Java 8,但我的猜测是
mylist.stream().sorted(new Comparator<Restaurant>() {
public int compare(Restaurant r1, Restaurant r2) {
// impl here how your restaurant should be compared
// (by rating or smth. else)
}
}).collect(groupingBy( .../ al the rest stuff here/ ...));
答案 2 :(得分:-2)
使用Java 8流API:
List<Restaurant> sortedList = mylist.stream()
.sorted((restaurant1, restaurant2) -> Long.compare(restaurant1.getRating(), restaurant2.getRating()))
.collect(Collectors.toList());