使用 java 流解析列表

Parsing a list using java streams

我的用例是我有 Restaurants 对象的列表,其属性为城市、类型、评级,我想按给定的(城市、类型)组合的最高评级打印列表。当我创建这个示例来混淆 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)*/
  }
}

我还没有使用 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/ ...));

使用 Java 8 流 API:

List<Restaurant> sortedList = mylist.stream()
.sorted((restaurant1, restaurant2) -> Long.compare(restaurant1.getRating(), restaurant2.getRating()))
.collect(Collectors.toList());

下面的代码片段应该会产生您想要的结果:

    List<Optional<Restaurant>> resultList = mymap.values()
                                                 .stream()
                                                 .flatMap(map -> map.values().stream())
                                                 .collect(Collectors.toList());

mymap.values().stream() 生成 Stream<Map<String, Optional<Restaurant>>>flatMap() 然后将该流映射到 Stream<Optional<Restaurant>>,并且 collect(Collectors.toList()) 将该流收集到 List<Optional<Restaurant>>

首先,您可以创建组合键来摆脱嵌套地图。 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());