Filtering on List based on one property with guava

前端 未结 2 1673
陌清茗
陌清茗 2021-01-04 07:58

I have a class called Person -

public class Person implements Nameable {
    private String name;

    public String getName(){
        return name;
    }
}         


        
相关标签:
2条回答
  • 2021-01-04 08:18

    Seems like you will have to manually iterate over both Lists (sounds lame, but that's the only thing I could think).

    outer loop: persons
       inner loop: subsetOfPersons
           compare person and sub person names and create another list with intersection of the      two
    
    0 讨论(0)
  • 2021-01-04 08:42

    I'm sure there's a simpler way... the below would transform person to name for the sake of comparison. For the subsetOfPersons, we actually create a list of names directly, since that's all we really need from them. For the persons, we keep the transformation limited to the context of the comparison.

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

    Edit: Thought you might appreciate a 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;
        }
    
    }
    

    Edit again: Missed the "not" requirement the first time. Easy fix--with predicates, you can just wrap with Predicates.not(..)!

    0 讨论(0)
提交回复
热议问题