【问题标题】:Java Streams: filtering with 2 objectsJava Streams:使用 2 个对象进行过滤
【发布时间】:2020-04-27 17:34:42
【问题描述】:

我有一个问题,我有一组连接两个地方的道路,我想在没有直接连接的情况下找到从 A 到 B 的所有连接,所以行程将从 A 到 X(甚至可能到 Y)给 B。 但是,当我已经知道没有直接连接时,我现在不知道如何过滤,因为我认为我需要超过 1 个对象。

routes = allroutes
    .stream()
    .filter(p -> p.getStart() == start)
    .filter(p,x -> p.getEnd() == x.getStart())
    .filter(x -> x.getEnd() ==  end)

和 filter(p,x....) 是不起作用的东西,但我不知道如何以不同的方式解决它。 当然,之前所有的流、列表等都已经正确初始化了。

【问题讨论】:

  • 首先,您需要找到从 A 到 B 的路径,正如您所说,该路径可以有很多中间点,因此对象的数量可能非常多。因此,流不是您正在做的事情的正确工具。重新考虑您要完成的工作。 --- 寻找路径(路线)的行为称为“graph theory”,以防您想对该主题进行一些研究
  • 嗯,有一个简单的解决方案和一个困难的解决方案,具体取决于集合的大小。更好的选择是使用 Graph 数据结构。请至少提供一些示例数据进行尝试。

标签: java filter java-stream


【解决方案1】:

由于您在此处同时需要列表中的两个值,因此我不确定使用流实现此目的的方法。 (其他人可能会发表评论。)但是,因为我发现这个问题很有趣,所以我很快在一个简单的 Java 类上尝试了它。我使用了一个简单的 for..each 循环而不是 Java 流。

public class RouteFinder{

    public static void main( String[] args ){
        List<Route> allroutes = new ArrayList<>();
        populateData( allroutes );

        findIndirectBetween( allroutes, "A", "B" ).forEach( System.out::println );
    }

    private static List<Route> findIndirectBetween( List<Route> allroutes, String start, String end ){
        List<Route> selected = new ArrayList<>();
        if( start.equals( end ) ) return selected;

        for( Route route : allroutes ) {
            List<String> rStops = route.getStops();
            if( !rStops.contains( start ) || !rStops.contains( end ) ) continue;

            int startIndex = rStops.indexOf( start );
            int endIndex = rStops.indexOf( end );
            if( startIndex != endIndex + 1 && startIndex != endIndex -1 ) selected.add( route );
        }

        return selected;
    }

    private static void populateData( List<Route> routes ) {
        routes.add( Route.of( "1", "A", "H", "C", "B" ) );
        routes.add( Route.of( "2", "A", "B" ) );
        routes.add( Route.of( "3", "C", "K", "L", "Z" ) );
        routes.add( Route.of( "4", "C", "L", "Z" ) );
        routes.add( Route.of( "5", "C", "B", "Z", "A" ) );
    }

    private static class Route{
        private String routeNumber;

        private List<String> stops = new ArrayList<>();

        public Route( String routeNumber, List<String> stops) {
            super();
            this.routeNumber = routeNumber;
            this.stops = stops;
        }

        public static Route of( String number, String... stops ) {
            List<String> ss = new ArrayList<>();
            if( stops != null ) for( String s : stops ) ss.add( s );

            return new Route( number, ss );
        }

        public String getStart() {
            if( this.stops != null && this.stops.size() > 0 ) return this.stops.get( 0 );
            return "";
        }

        public String getEnd() {
            if( this.stops != null && this.stops.size() > 0 ) return this.stops.get( this.stops.size() - 1 );
            return "";
        }

        public List<String> getStops(){
            return this.stops;
        }

        public String getRouteNumber(){
            return routeNumber;
        }

        @Override
        public String toString(){
            return "routeNumber=" + routeNumber + ", stops=" + stops;
        }
    }
}

编辑:

再想一想,我认为有一种方法可以使用流。

private static List<Route> findIndirectBetweenUsingStreams( List<Route> allroutes, String start, String end ){
    return allroutes.stream()
            .filter( r -> r.getStops().contains( start ) ) //Retain routes which have "start"ing point
            .filter( r -> r.getStops().contains( end ) ) //Retain routes which have "end" point
            .collect( ArrayList::new, ( newRouteList, r ) -> {
                List<String> rStops = r.getStops();
                int startIndex = rStops.indexOf( start );
                int endIndex = rStops.indexOf( end );
                if( startIndex != endIndex + 1 && startIndex != endIndex -1 ) newRouteList.add( r );
            },
                ( newRouteList, r ) -> {} );
}

此代码使用模型Route和我上面粘贴的类中的基本代码。可以调用这个方法来代替findIndirectBetween()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-28
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多