2016-02-04 76 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]