2011-04-26 45 views
12

我有一個名爲Person類 -與過濾列表基於與番石榴一個屬性

public class Person implements Nameable { 
    private String name; 

    public String getName(){ 
     return name; 
    } 
} 

現在我有兩個表 -

List<Person> persons = // some persons 
List<Person> subsetOfPersons = // some duplicate persons, but different objects and don't share the same identity 

現在我想過濾的persons哪些不是目前在subsetOfPersons,平等標準是名稱屬性和人沒有等於。

我該怎麼做?

回答

9

我敢肯定,有一種更簡單的方法...爲了比較起見,下面的內容會將人物變爲名稱。對於subsetOfPersons,我們實際上直接創建了一個名稱列表,因爲這是我們真正需要的。對於persons,我們將轉換限制在比較的上下文中。

Iterable<Person> filtered = Iterables 
      .filter(
       persons, 
       Predicates.not(
        Predicates.compose(
         Predicates.in(ImmutableSet.copyOf(Iterables.transform(subsetOfPersons, personToNamefunction))), 
         personToNamefunction 
        ) 
       ) 
      ); 

編輯:想你可能欣賞一個JUnit:再次

package com.stackoverflow.test; 

import static org.junit.Assert.*; 

import java.util.Iterator; 

import org.junit.Test; 

import com.google.common.base.Function; 
import com.google.common.base.Predicates; 
import com.google.common.collect.ImmutableList; 
import com.google.common.collect.ImmutableSet; 
import com.google.common.collect.Iterables; 

public class PersonTest { 
    public class Person { 
     private String name; 

     public String getName(){ 
      return name; 
     } 

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

    @Test 
    public void testNameBasedFiltering() { 
     Person bob = createPerson("bob"); 
     Person jim = createPerson("jim"); 
     Person pam = createPerson("pam"); 
     Person roy = createPerson("roy"); 

     ImmutableList<Person> persons = ImmutableList.of(
       bob, 
       jim, 
       pam, 
       roy); 
     ImmutableList<Person> subsetOfPersons = ImmutableList.of(
       createPerson("jim"), 
       createPerson("pam")); 

     Function<Person, String> personToNamefunction = new Function<Person, String>() { 
      public String apply(Person arg0) { 
       return arg0.getName(); 
      } 
     }; 

     Iterable<Person> filtered = Iterables 
       .filter(
        persons, 
        Predicates.not(
         Predicates.compose(
          Predicates.in(ImmutableSet.copyOf(Iterables.transform(subsetOfPersons, personToNamefunction))), 
          personToNamefunction 
         ) 
        ) 
       ); 

     for (Person person : filtered) { 
      assertNotSame(jim, person); 
      assertNotSame(pam, person);   
     } 
    } 

    public Person createPerson(String name) { 
     Person person = new Person(); 
     person.setName(name); 

     return person; 
    } 

} 

編輯:錯過了 「不」 要求的第一次。易於修復 - 帶謂詞,你可以包裝Predicates.not(..)

+1

甚至沒有想到Predicates.compose,好! – sjr 2011-04-26 17:44:16

+0

我想他不想(在(nameSet)) – sjr 2011-04-26 17:45:01

+0

感謝您的召集。用not包裝謂詞,並更新JUnit以反映變化。 – Ray 2011-04-26 17:50:23

0

好像你將不得不手動迭代兩個列表(聽起來很蹩腳,但這是我能想到的唯一的東西)。

outer loop: persons 
    inner loop: subsetOfPersons 
     compare person and sub person names and create another list with intersection of the  two 
+0

忽略我的回覆,上面的一個比我的好。我仍然保持這裏,以顯示好的和壞的程序員分開的東西...... – Sid 2011-04-26 17:18:16

+0

它不壞所有:) – Premraj 2011-04-26 17:22:14