1

What is the most concise way to 'backup' a state of a collection while iterating with java stream API?

For example, how could I 'implement' .backup(allRules)?

ArrayList<String> allRules = new ArrayList<>(); 
Set<String> businessRules = result.getRules().stream()
        .map(name -> replace(name, RULES_PACKAGE_NAME, EMPTY))
        .backup(allRules)
        .filter(name -> !NON_BUSINESS_RULES.contains(name))
        .collect(toSet());
Viktor Mellgren
  • 4,318
  • 3
  • 42
  • 75
Mike
  • 20,010
  • 25
  • 97
  • 140
  • 1
    It is not really clear what you want the `backup` method to do. Please explain that more clearly and in more detail. What output do you expect from this method? – Jesper Mar 24 '17 at 13:21
  • Where do you want to persist? – bichito Mar 24 '17 at 13:24
  • I want to backup all rules short names and then continue to colloct business rules from an example. I would like to 'save' all rules short names into 'allRules' collection and business rules to 'businessRules' collection. – Mike Mar 24 '17 at 13:25

3 Answers3

1

Just do it in two steps?

   List<String> allRules = result.getRules().stream()
        .map(name -> replace(name, RULES_PACKAGE_NAME, EMPTY))
        .collect(Collectors.toList());

    Set<String> businessRules = allRules.stream()
        .filter(name -> !NON_BUSINESS_RULES.contains(name))
        .collect(toSet());
Viktor Mellgren
  • 4,318
  • 3
  • 42
  • 75
0
    ArrayList<String> allRules = new ArrayList<>(); 
    Set<String> businessRules = result.getRules().stream()
            .map(name -> replace(name, RULES_PACKAGE_NAME, EMPTY))
            .peek(allRules::add)
            .filter(name -> !NON_BUSINESS_RULES.contains(name))
            .collect(toSet());
Mike
  • 20,010
  • 25
  • 97
  • 140
  • There are [several ways this can break](http://stackoverflow.com/a/33636377/2711488). It’s not clear, why you think that this abuse of `peek` has any advantage over a straight-forward `List allRules = result.getRules().stream() .map(name -> replace(name, RULES_PACKAGE_NAME, EMPTY)) .collect(toList()); Set businessRules = allRules .stream() .filter(name -> !NON_BUSINESS_RULES.contains(name)) .collect(toSet());` – Holger Mar 24 '17 at 13:59
0

The above scenario envisions a stream process that has a side effect, which feels somewhat sketchy unless that side effect happens within the bounds of a forEach. The forEach operation is also a terminal operation, which means it shouldn't suffer from the same problem as the "abuse" of peek would or any other approach that couldn't ensure that every element in the stream would pass though the backup operation. In any case, I would suggest the following solution:

List<String> allRules = new ArrayList<>(); 
Set<String> businessRules = new HashSet<>();

result.getRules()
      .stream()
      .map(name -> replace(name, RULES_PACKAGE_NAME, EMPTY))
      .forEach(name-> {
          allRules.add(name);
          if(!NON_BUSINESS_RULES.contains(name)) {
              businessRules.add(name);
          }
      });
John Morris
  • 396
  • 2
  • 10