繁体   English   中英

Java Streams:用 2 个对象过滤

[英]Java Streams: filtering with 2 objects

我的问题是,我有一系列连接两个地方的道路,我想在没有直接连接的情况下找到从 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....) 是不起作用的东西,但我不知道如何以不同的方式解决它。 当然,所有流、列表等之前都已正确初始化。

由于您在此处同时需要列表中的两个值,因此我不确定使用流实现此目的的方法。 (其他人可能会发表评论。)但是,因为我发现这个问题很有趣,所以我很快就在一个简单的 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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM