当分配全局变量时,如何将带有嵌套ifs的for循环映射到Java 8流中

时间:2017-03-07 18:54:52

标签: java for-loop foreach java-8 java-stream

我一直在尝试学习Java 8 .stream(),并将其作为转换此for-loop的一部分。我无法通过正确的方式来解决这个问题。 .map,和.forEach似乎没有帮助。

当我尝试将DateFormat releaseDate分配给已解析的records.getReleaseDate()对象,然后将其与set beforeDate对象进行比较时,我的主要问题就出现了。有什么想法吗?

.get

这是我对.stream()的初步处理方法:

DateFormat sourceFormat = new SimpleDateFormat("yyyy.MM.dd");
Date releaseDate = new Date();
Date beforeDate;

beforeDate = sourceFormat.parse("2001.01.01");

Records records = (Records) obj;

for (Record recs : records.getRecordsList()) {
    try {
        releaseDate = sourceFormat.parse(((Record) recs).getReleaseDate());
    } catch (ParseException e) {
        System.err.println("PARSE EXCEPTION. Unable to parse record.getReleaseDate()");
        e.printStackTrace();
    }

    if (((Record) recs).getTrackListing().size() > 10) {
        if (releaseDate.before(beforeDate)) {
            Release release = new Release();
            release.setName(((Record) recs).getName());
            release.setTrackCount(((Record) recs).getTrackListing().size());
            data.add(release);
        }
    }
}

2 个答案:

答案 0 :(得分:0)

还没有真正测试过代码,我希望这个想法很明确。我会做这样的事情:

final DateFormat sourceFormat = new SimpleDateFormat("yyyy.MM.dd");
final Date beforeDate = sourceFormat.parse("2001.01.01");

((Records) obj).getRecordsList()
        .stream()
        .filter(rec -> rec.getTrackListing().size() > 10)
        .filter(rec -> {
            try {
                return sourceFormat.parse(rec.getReleaseDate()).before(beforeDate));
            } catch (ParseException e) {
                System.err.println("PARSE EXCEPTION. Unable to parse record.getReleaseDate()");
                e.printStackTrace();
                return null;
            }
        })
        .filter(Objects::nonNull)
        .map(rec -> {
            Release release = new Release();
            release.setName(rec.getName());
            release.setTrackCount(rec.getTrackListing().size());
            return release;
        })
        .collect(Collectors.toList());

顺便说一句,如果您使用Java 8,我建议您使用new date/time api来避免ParseException和null检查,这样会更清晰。

答案 1 :(得分:0)

我理解您的问题,您不知道如何使用.map.forEach流媒体功能。 .map用于保留"流" alive并映射流经流的实际对象/值(在您的情况下,从Record的实例到Release的实例)。 .forEach是一个接收器,因此流始终以forEach结束。因此,您希望使用.map(请参阅http://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/)。

您的源代码已经存在一些问题:

  1. 如果解析releaseDate并抛出异常怎么办? releaseDate的值不会更改(可能是new Date()或前一记录的值。
  2. 为什么即使解析releaseDate,如果仅getTrackListing().size() > 10使用它?我只有在检查条件true后才解析它。
  3. 使用lambdas你的"外部变量"必须final才能在流中使用。
  4. 也就是说,为了让您的工作正常,您仍然需要map recs release

    // see 3.
    final Date beforeDate = sourceFormat.parse("2001.01.01");
    
    records.getRecordsList().stream()       
        .filter(r -> r.getTrackListing().size() > 10)
        .filter(r - {
           // if the parsedDate is invalid we don't want to process, see 1. and 2.
           Date parsedDate;
           try {
              parsedDate = sourceFormat.parse(r.getReleaseDate());
           } catch (ParseException e) {
              System.err.println("...");
              e.printStackTrace();
              parsedDate = null;
           }
    
           return parsedDate != null && parsedDate.before(beforeDate);
        })
        .map(r -> {
           // map the records to an release
           Release release = new Release();
           release.setName(r.getName());
           release.setTrackCount(r.getTrackListing().size());
           return release;
        })
        .collect(Collectors.toList()));
    

    我只是复制并粘贴你的代码(并修复了明显的语法错误),所以仔细看看!