[英]How to filter map and return list of values
我正在尝试创建一个函数来过滤一个映射,该映射包含一个字符串作为键和一个 Flight 对象列表作为值并返回一个字符串列表。 地图代表飞行路径,任务是找到从起点到终点的最短路径。 航班类有两个字段,origin 和 destination。 所以如果我发送给纽约的维也纳,我应该得到一个包含 fligth1 和 flight2 的列表。 该函数接受两个参数(字符串来源,字符串目的地)
地图中的键代表一个城市,而值是航班到达的位置,如下所示:
Map<String, List<Flight>> paths = new HashMap<>();
List<Flight> flightsToBerlin = new ArrayList<>();
List<Flight> flightsToVienna = new ArrayList<>();
Flight flight1 = new Flight("Vienna", "Berlin");
Flight flight2 = new Flight("Berlin", "New York");
flightsToBerlin.add(flight1);
flightsToVienna.add(flight2);
paths.put("Vienna", flightsToVienna);
paths.put("Berlin", flightsToBerlin);
诀窍是要求它在一行中完成。 这是让我发疯的部分。 我曾尝试使用流,但在过滤地图并找到目的地后我有点困惑,如下所示:
public List<Flight> findPath(String origin, String destination) {
return (List<Flight>) this.paths.entrySet().stream()
.filter(x -> x.getKey().equals(destination))..
}
我如何从这里开始?
你可以这样做:
return Stream.of(
paths.values()
.stream()
.flatMap(Collection::stream)
.collect(Collectors.groupingBy(Flight::getStartingLocation))
).flatMap(flights ->
Stream.of(
new HashMap<>(Map.of(origin, new Flight(origin, origin)))
).peek(back ->
Stream.iterate(
List.of(origin),
list -> list.stream().flatMap(
now -> flights.getOrDefault(now, Collections.emptyList()).stream()
.filter(flight -> back.putIfAbsent(flight.getDestination(), flight) == null)
.map(Flight::getDestination)
).collect(Collectors.toList())
).filter(list -> list.contains(destination)).findFirst()
).map(back ->
Stream.iterate(
new Flight(destination, null),
now -> back.get(now.getStartingLocation())
)
.skip(1)
.takeWhile(flight -> !flight.getDestination().equals(origin))
.collect(Collectors.toList())
)
)
.map(ArrayList::new)
.peek(Collections::reverse)
.findFirst().get();
试试下面的代码:
return (List<Flight>) paths.entrySet()
.stream()
.filter(x -> x.getKey().equals(destination))
.map(Map.Entry::getValue)
.flatMap(List::stream)
.collect(Collectors.toList());
你所要求的几乎是不可能的。 但是,我能够制作出一种大多数情况下有效的单线。 它的主要限制是它只能找到两个航班才能让您到达目的地。 换句话说:
Berlin -> Vienna | WORKS
New York -> Berlin -> Vienna | WORKS
Boston -> New York -> Berlin -> Vienna | DOESN'T WORK
我通常会花时间解释我在回答中做了什么以及为什么,但这是 Java 语言中如此凌乱、复杂、低效的可憎之处,我怀疑我是否能很好地解释它。 以下是在解释发生了什么事我最好的尝试,但不是为什么它正在发生:
如果没有匹配给定起点和目的地的航班,则比较每个匹配起点或目的地的航班,看看是否有任何航班与给定的参数和给定的参数同时匹配。 例子:
(A1) (A2) findPath(Boston, Tokyo) (B1) (B2) B1 aligns with A1 Flight[Boston, Istanbul] C2 aligns with A2 C1 aligns with B2 (C1) (C2) Flight[Istanbul, Tokyo]
在实现代码之前,您将需要以下导入:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
我还假设您的Flight
类看起来像这样:
public class Flight {
private String origin;
private String dest;
public Flight(String origin, String dest) {
this.origin = origin;
this.dest = dest;
}
public String getOrigin() {
return origin;
}
public String getDestination() {
return dest;
}
}
好的,这是你的单线:
@SuppressWarnings("unchecked")
public List<Flight> findPath(String origin, String destination) {
return new ArrayList<Flight>((Collection<Flight>) this.paths.values().stream().map(l -> l.stream().filter(f -> f.getDestination().equalsIgnoreCase(destination)|| f.getOrigin().equalsIgnoreCase(origin)).collect(Collectors.toList())).map(t -> new Object[] { t.stream().filter(f -> f.getDestination().equalsIgnoreCase(destination)&& f.getOrigin().equalsIgnoreCase(origin)).findAny(), t }).map(t -> ((Optional<Flight>) t[0]).isPresent() ? ((Optional<Flight>) t[0]).get() : t[1]).reduce((t, u) -> t instanceof Flight ? new HashSet<Flight>(Arrays.asList((Flight) t)): t instanceof HashSet ? t: u instanceof Flight ? new HashSet<Flight>(Arrays.asList((Flight) u)): u instanceof HashSet ? u: Stream.concat(((List<Flight>) t).stream().filter(f1 -> (f1.getDestination().equalsIgnoreCase(destination)&& ((List<Flight>) u).stream().anyMatch(f2 -> f1.getOrigin().equalsIgnoreCase(f2.getDestination())))|| (f1.getOrigin().equalsIgnoreCase(origin)&& ((List<Flight>) u).stream().anyMatch(f2 -> f1.getDestination().equalsIgnoreCase(f2.getOrigin())))),((List<Flight>) u).stream().filter(f1 -> (f1.getDestination().equalsIgnoreCase(destination)&& ((List<Flight>) t).stream().anyMatch(f2 -> f1.getOrigin().equalsIgnoreCase(f2.getDestination())))|| (f1.getOrigin().equalsIgnoreCase(origin)&& ((List<Flight>) t).stream().anyMatch(f2 -> f1.getDestination().equalsIgnoreCase(f2.getOrigin()))))).collect(Collectors.toList())).get());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.