I have a class called Person -
我有一门课叫Person -
public class Person implements Nameable {
private String name;
public String getName(){
return name;
}
}
Now I have two lists -
现在我有两个列表
List<Person> persons = // some persons
List<Person> subsetOfPersons = // some duplicate persons, but different objects and don't share the same identity
Now I would like to filter the persons
which are not present in the subsetOfPersons
, equality criteria is name property and Person doesn't have equals.
现在我想要过滤掉subsetOfPersons中没有的人,平等标准是name property而Person则没有equal。
How can I do this?
我该怎么做呢?
2 个解决方案
#1
9
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.
我相信有更简单的方法……下面是为了比较而变换人名。对于subsetOfPersons,我们实际上直接创建了一个名称列表,因为这是我们真正需要的。对于个人而言,我们将转型局限于比较的语境。
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:
编辑:你可能会欣赏JUnit:
package com.*.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(..)
!
再次编辑:第一次错过了“not”要求。简单修复——使用谓词,您可以使用谓词进行包装。
#2
0
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
#1
9
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.
我相信有更简单的方法……下面是为了比较而变换人名。对于subsetOfPersons,我们实际上直接创建了一个名称列表,因为这是我们真正需要的。对于个人而言,我们将转型局限于比较的语境。
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:
编辑:你可能会欣赏JUnit:
package com.*.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(..)
!
再次编辑:第一次错过了“not”要求。简单修复——使用谓词,您可以使用谓词进行包装。
#2
0
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