簡體   English   中英

Java Guava過濾兩個具有不同類型的集合

[英]Java Guava filter two collection with different type

我有兩個收藏:

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() {
    }
}

我要創建(最好的結果是修改newA和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甚至最好的辦法?

使用Java 8 Streams 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流一樣工作。 因此,您實際上可以像以前一樣使用transform。 如果絕對不想這樣做,這是番石榴的完整示例:

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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM