使用流过滤对象列表很困难

时间:2019-06-20 11:01:44

标签: java java-stream

我有一个列表List,在以下两种情况下,需要编写基于流的通用代码来过滤出对象。

  1. 输入参数为dp,值为“ MAR 2019”。如果找到任何匹配的行,并且结束日期不为null,则返回该行。

    输入:

    [PT(pn=1, endDate=2019-01-11, dp=MAR 2019),           
    PT(pn=4, endDate=null, dp=APR 2019),        
    PT(pn=6, endDate=2019-05-11, dp=MAY 2019)]       
    

    输出:

    PT(pn=1, endDate=2019-01-11, dp=MAR 2019)}     
    
  2. 该功能的参数为“ MAR 2019”。如果找到任何匹配的行且结束日期为null,则需要返回所有记录,直到获得非空的结束日期

    输入:

    [PT(pn=1, endDate=null, dp=MAR 2019),      
    PT(pn=4, endDate=2019-04-11, dp=APR 2019),       
    PT(pn=6, endDate=2019-05-11, dp=MAY 2019)]      
    

    输出:

    [PT(pn=1, endDate=null, dp=MAR 2019),      
    PT(pn=4, endDate=2019-04-11, dp=APR 2019)]  
    
class PT{       
   Integer pn;      
   Date endDate;      
   String dp;       
} 
List<PT> filteredList11 = availablePT.get()
    .stream()
    .sorted(Comparator.comparing(PT::getPn))
    .filter(e->)
    .collect(Collectors.toList());

对于在上述情况下如何编写一个过滤函数,我有点困惑,因为我们从来没有在使用流时捕获任何先前的状态值,请注意。

2 个答案:

答案 0 :(得分:0)

这里是一种方法的示例,该方法可以在问题的第一部分中完成您想做的事情。基本上,这仅使用一条List<PT>语句来流式处理和过滤给定的.filter

public class StackoverflowMain {

    static class PT {
        Integer pn;
        // Here, I changed your code. You should really use the up-to-date time API
        LocalDate endDate;
        String dp;

        public PT(int pn, LocalDate endDate, String dp) {
            this.pn = pn;
            this.endDate = endDate;
            this.dp = dp;
        }
    }

    /**
     * <p>
     * Gets a list of all PTs that match the given criterium for the dp class
     * attribute of class PT.
     * </p>
     *
     * @param source the original list that needs to be filtered
     * @param dp     the dp value to be matched
     * @return a list of all PTs that passed the filter criterium
     */
    public static List<PT> getPTWithValidEndDateAndDp(List<PT> source, String dp) {
        return source.stream()
                    .filter(pt -> pt.endDate != null && pt.dp.equals(dp))
                    .collect(Collectors.toList());
    }

    public static void main(String args[]) {
        // mock the list of PTs that you receive from somewhere
        List<PT> receivedPTs = new ArrayList<PT>();
        // one PT with endDate == null but matching dp
        receivedPTs.add(new PT(1, null, "MAR 2019"));
        // one PT with valid endDate and valid dp, but no matching dp
        receivedPTs.add(
            new PT(4, LocalDate.parse("2019-04-11", DateTimeFormatter.ISO_DATE), "APR 2019")
        );
        // another totally valid PT whose dp does not match
        receivedPTs.add(
            new PT(6, LocalDate.parse("2019-05-11", DateTimeFormatter.ISO_DATE), "MAY 2019")
        );
        // a totally valid PT with the matching dp ---> should be contained in the output
        receivedPTs.add(
            new PT(1, LocalDate.parse("2019-03-11", DateTimeFormatter.ISO_DATE), "MAR 2019")
        );

        // create a list from the valid and matching PTs passing the source list and the
        // dp to be matched
        List<PT> marchPTs = getPTWithValidEndDateAndDp(receivedPTs, "MAR 2019");

        // output the result
        marchPTs.forEach(mpt -> System.out.println("[pn: " + mpt.pn + ", endDate: "
                + mpt.endDate.format(DateTimeFormatter.ISO_DATE) + ", dp: " + mpt.dp + "]"));
    }
}
  

请注意,我更改了代码的一部分,将java.util.Date的老式且容易出错的用法替换为java.time.LocalDate,这在当今应是首选。

我不知道我是否有足够的时间为您的第二个要求提供示例,但我会尝试…

答案 1 :(得分:0)

第1部分:

public static List<PT> filterOne(List<PT> input, String dp) 
{
    return input.stream()
             .filter(pt -> pt.endDate != null && pt.dp.equals(dp))
             .collect(Collectors.toList());
}

第2部分:

public static List<PT> filterTwo(List<PT> input, String dp) 
{
    AtomicBoolean dpFilter = new AtomicBoolean(false);

    return input.stream()
            .filter(obj -> {
                if (dpFilter.get()){
                    if (obj.endDate == null || obj.dp.equals(dp)) {
                        dpFilter.set(false);
                        return false;
                    }
                    return true;
                }
                if (obj.endDate == null && obj.dp.equals(dp)){
                    dpFilter.set(true);
                    return true;
                }
                return false;
            })
            .collect(Collectors.toList());
}