2016-02-04 77 views
2

我这里的示例基于简单的逻辑转换的java 7嵌套for循环用java 8流API

给定一个输入列表和分组的对象的列表,其具有列表字段中,这基本上返回列表方法应该返回一个列表,其中包含grouping.list的所有成员,如果grouping.name匹配输入列表中的任何字符串,或者只是将输入字符串添加到返回列表中。

在我写这段代码后,我认为它可以在Java 7中变得更简单,并且更好地使用Java 8 Streaming API。

public class CollectorExample { 

    public static void main(String[] args){ 

     List<String> input = new ArrayList<>(); 
     input.add("foo"); 
     input.add("bar"); 
     input.add("foobar"); 
     input.add("java"); 

     List<String> list1 = new ArrayList<>(); 
     list1.add("hello"); 
     list1.add("world"); 

     List<String> list2 = new ArrayList<>(); 
     list2.add("spring"); 
     list2.add("multi-threaded"); 


     Grouping g1 = new Grouping("foobar",list1); 
     Grouping g2 = new Grouping("java",list2); 

     List<Grouping> groupingList = new ArrayList<>(); 
     groupingList.add(g1); 
     groupingList.add(g2); 


     System.out.println(mapAndMerge(input,groupingList)); 


    } 


    public static List<String> mapAndMerge(List<String> input, List<Grouping> groupingList){ 

     Set<String> returnDocs = new HashSet<>(); 
     Iterator<String> it = input.iterator(); 
     while(it.hasNext()){ 
      String doc = it.next(); 
      boolean found = false; 
      for (Grouping lg : groupingList){ 
       if (lg.getName().equals(doc)){ 
        returnDocs.addAll(lg.getList()); 
        found=true; 
        } 
       } 
      if (!found){ 
       returnDocs.add(doc); 
      } 
     } 
    return new ArrayList<>(returnDocs); 
    } 

} 

class Grouping { 

    List<String> list; 
    String name; 

    public Grouping(String name, List<String> list){ 
     this.list=list; 
     this.name=name; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public List<String> getList() { 
     return list; 
    } 

    public void setList(List<String> list) { 
     this.list = list; 
    } 


} 

这输出[spring, bar, world, foo, hello, multi-threaded]这是正确的。 这是我尝试过的Java 8语法,并且无法工作;

//  List<String> mergedDocs = 
//    input.forEach(doc-> 
//         groupingList.stream().map(g -> g.getName().equals(doc) ? e.getList() : doc).collect(Collectors.toList())); 
//  return mergedDocs; 
+4

请用您自己的话来解释代码的意图。 –

回答

1

你可以重新写用java 8. mapAndMerge方法如下方式,但它并不像你一样非常简洁。

public static List<String> mapAndMerge(List<String> input, 
     List<Grouping> groupingList) { 

     Set<String> returnDocs = input 
     .stream() 
     .map(t -> groupingList 
      .stream() 
      .filter(g -> g.getName().equals(t)) 
      .map(v -> v.getList()) 
      .findAny() 
      .orElse(Arrays.asList(t))) 
     .flatMap(t -> t.stream()) 
     .collect(Collectors.toSet()); 

     return new ArrayList<>(returnDocs); 
    } 
+0

其实听起来好多了。我使用布尔值,我不想在Java 7中。你可以在Java 7中重构相同的布尔值。 –

0

我想,如果你使用Map代替Grouping类这将是更简单,更清晰。

所以,这就是你必须在main()方法:

Map<String, List<String>> groupingMap = new HashMap<>(); 
    groupingMap.put("foobar", list1); 
    groupingMap.put("java", list2); 

    List<String> mergedDocs = new ArrayList<>(); 
    input.stream() 
     .map(doc -> groupingMap.getOrDefault(doc, Collections.singletonList(doc))) 
     .forEach(mergedDocs::addAll); 

    System.out.println(mergedDocs); 
2

可以使这个很多简单通过不使用你的Grouping类,但用一个简单的Map<String, List<String>>代替。这张地图将作为分组,持有给定名称的列表。这也使得有更好的性能,因为查看地图是恒定时间(而您的解决方案是线性时间,因为它遍历分组以找到匹配的分组)。

如果必须使用List<Grouping>,仍然可以预先处理它要转换为一中间Map

mapAndMerge方法简单地变为:

public static List<String> mapAndMerge(List<String> input, List<Grouping> groupingList) { 
    Map<String, List<String>> map = groupingList.stream().collect(Collectors.toMap(Grouping::getName, Grouping::getList)); 
    return input.stream() 
       .flatMap(s -> map.getOrDefault(s, Arrays.asList(s)).stream()) 
       .collect(Collectors.toList()); 
} 

每个输入被平面映射到列表中包含的地图或包含当前元素的默认列表。然后将其收集到一个新的列表中。此代码打印:

[foo, bar, hello, world, spring, multi-threaded]