2016-01-31 40 views
1

我有兩個集合:Java的番石榴過濾器兩個收集不同類型

ArrayList<B> currentB = new ArrayList<B>(); 
{ 
    currentB.add(new B(new A("1"))); 
    currentB.add(new B(new A("2"))); 
    currentB.add(new B(new A("7"))); 
    currentB.add(new B(new A("3"))); 
    currentB.add(new B(new A("4"))); 
} 
ArrayList<A> newA = new ArrayList<A>(); 
{ 
    newA.add(new A("1")); 
    newA.add(new A("5")); 
    newA.add(new A("2")); 
    newA.add(new A("6")); 
    newA.add(new A("7")); 
    newA.add(new A("8")); 

} 

收藏有以下幾種類型:

class A { 
    private String id; 

    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (o == null || getClass() != o.getClass()) return false; 

     A nodeRef = (A) o; 

     return !(id != null ? !id.equals(nodeRef.id) : nodeRef.id != null); 

    } 

    public A() { 
    } 

    public A(String id) { 
     this.id = id; 
    } 

    @Override 
    public String toString() { 
     return "NodeRef{" + 
       "id='" + id + '\'' + 
       '}'; 
    } 
} 

class B { 
    private A a; 

    public A a() { 
     return a; 
    } 

    public A getA() { 
     return a; 
    } 

    public void setA(A a) { 
     this.a = a; 
    } 

    @Override 
    public String toString() { 
     return "B{" + 
       "a=" + a + 
       '}'; 
    } 

    public B(A a) { 
     this.a = a; 
    } 

    public B() { 
    } 
} 

我想創建(最好的結果就是修改紐瓦和currentB)兩大列表:

  • 第一個應該有對象,其中沒有代表
    一(例如 - a(3),a(4)); (a)(5),a(6), a(8))。

我可以做的番石榴,但它需要創建3集:

Function<B, A> BtoA = new Function<B, A>() { 
    public A apply(final B b) { 
     return b.getA(); 
    } 
}; 
Collection<A> currentA = Collections2.transform(currentB, BtoA); 

java.util.Collection<A> idToDelete = Collections2.filter(currentA, Predicates.not(Predicates.in(newA))); 
java.util.Collection<A> idToAdd = Collections2.filter(newA, Predicates.not(Predicates.in(currentA))); 

System.out.println("Old B" + idToDelete); 
System.out.println("New A" + idToAdd); 

有擺脫Collection.transform方式或者即使是最好的方法是什麼?

回答

3

它看起來相當不錯與Java 8流API:

java.util.Collection<String> idToDelete = 
     currentB.stream() //get the stream 
     .filter(b -> !newA.contains(b.getA())) // filter those b, whose A is in newA 
     .map(b -> b.getA().id) // map transform to get just an Id (you can use just getA() here) 
     .collect(Collectors.toList()); // finally transform back to list 

java.util.Collection<String> idToAdd = 
     newA.stream() // again get stream 
     .filter(
       // this is a little bit fancy... 
       // only leave those A, for which currentB doesn't contain element, that has getA() equals to that A 
       a -> currentB.stream().noneMatch(
         b -> b.getA().equals(a) 
       ) 
     ) 
     .map(a -> a.id) // again get id 
     .collect(Collectors.toList()); // transform to list 

[編輯:]

如果你看看番石榴的源代碼,你可以看到,transform只是包裝現有一個用一個轉換函數。所以番石榴基本上就像java 8流一樣工作。所以你可以像你一樣使用變換。如果絕對不想這樣做,這是番石榴的完整示例:

Function<B, A> BtoA = new Function<B, A>() { 
    public A apply(final B b) { 
     return b.getA(); 
    } 
}; 
Function<A, String> aToId = new Function<A, String>() { 
    public String apply(final A a) { 
     return a.getId(); 
    } 
}; 

java.util.Collection<B> bToDelete = Collections2.filter(currentB, Predicates.compose(Predicates.not(Predicates.in(newA)), BtoA)); 

//without transform, looks ugly 
java.util.Collection<A> aToAdd = Collections2.filter(newA, new Predicate<A>() { 
    @Override 
    public boolean apply(final A a) { 
     return !Iterables.any(currentB, new Predicate<B>() { 
      @Override 
      public boolean apply(B b) { 
       return b.getA().equals(a); 
      } 
     }); 
    } 
}); 
// this is essentially the same, you can safely use transform 
//java.util.Collection<A> aToAdd = Collections2.filter(newA, Predicates.not(Predicates.in(Collections2.transform(currentB, BtoA)))); 

java.util.Collection<String> idToDelete = Collections2.transform(bToDelete, Functions.compose(aToId, BtoA)); 
java.util.Collection<String> idToAdd = Collections2.transform(aToAdd, aToId); 

System.out.println("Old B: " + idToDelete); 
System.out.println("New A: " + idToAdd); 
+0

它的工作更快 - 謝謝。但我有一個限制 - 我只能使用java7。有沒有辦法不使用java8? –

+0

我編輯了答案,用番石榴添加了工作樣本。 –

+0

感謝您的解釋。所以Guava沒有另一種('beaty')方法(只需調用一個包含所有參數的函數)? –