2015-12-07 20 views
5

Mój przypadek jest:Znajdź element pasujący w 2 listach używając Java 8 strumień

class Person { 
    String id ; 
    String name; 
    String age; 
} 
List<Person> list1 = {p1,p2, p3}; 
List<Person> list2 = {p4,p5, p6}; 

Chcę wiedzieć, czy jest osobą list1 który ma taką samą nazwę i wiek w list2 ale nie przeszkadza o id .

Co jest najlepszy i szybki sposób?

+0

w moim przypadku jest równy nie może być overrided – TNN

Odpowiedz

3

Zdefiniuj sobie kluczowy obiekt, który przechowuje i porównuje pożądane właściwości.W tym prostym przypadku możesz użyć małej listy, podczas gdy każdy indeks odpowiada jednej właściwości. W bardziej skomplikowanych przypadkach można użyć Map (używając nazwy właściwości jak klucze) lub dedykowaną klasę:

Function<Person,List<Object>> toKey=p -> Arrays.asList(p.getName(), p.getAge()); 

z taką funkcją mapowania. możesz użyć prostego rozwiązania:

list1.stream().map(toKey) 
    .flatMap(key -> list2.stream().map(toKey).filter(key::equals)) 
    .forEach(key -> System.out.println("{name="+key.get(0)+", age="+key.get(1)+"}")); 

co może prowadzić do niskiej wydajności, gdy masz dość duże listy. Gdy masz duże listy (lub nie jest w stanie przewidzieć ich rozmiary), należy użyć pośrednią Set przyspieszyć wyszukiwanie (zmiana czasu złożoność zadania jest od O(n²) do O(n)):

list2.stream().map(toKey) 
    .filter(list1.stream().map(toKey).collect(Collectors.toSet())::contains) 
    .forEach(key -> System.out.println("{name="+key.get(0)+", age="+key.get(1)+"}")); 

W powyższych przykładach, każdy mecz zostanie wydrukowany. Jeśli jesteś zainteresowany tylko tym, czy istnieje taki mecz, można użyć albo:

boolean exists=list1.stream().map(toKey) 
    .anyMatch(key -> list2.stream().map(toKey).anyMatch(key::equals)); 

lub

boolean exists=list2.stream().map(toKey) 
    .anyMatch(list1.stream().map(toKey).collect(Collectors.toSet())::contains); 
0

Musisz powtórzyć dwie listy i porównać atrybuty.

for(Person person1 : list1) { 
    for(Person person2 : list2) { 
     if(person1.getName().equals(person2.getName()) && 
       person1.getAge().equals(person2.getAge())) { 
      //your code 
     } 
    } 
} 
+0

potrzebują lepszego java8 stream way :) – TNN

7

Prostym sposobem na to jest, aby zastąpić equals i hashCode. Ponieważ zakładam, że równość między Person należy również wziąć pod uwagę pole id można owinąć to wystąpienie do PersonWrapper która będzie realizować poprawne equals i hashCode (czyli sprawdzić tylko pola name i age):

class PersonWrapper { 

    private Person person; 

    private PersonWrapper(Person person) { 
     this.person = person; 
    } 

    public static PersonWrapper wrap(Person person) { 
     return new PersonWrapper(person); 
    } 

    public Person unwrap() { 
     return person; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) { 
      return true; 
     } 
     if (obj == null || getClass() != obj.getClass()) { 
      return false; 
     } 
     PersonWrapper other = (PersonWrapper) obj; 
     return person.name.equals(other.person.name) && person.age.equals(other.person.age); 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + person.name.hashCode(); 
     result = prime * result + person.age.hashCode(); 
     return result; 
    } 

} 

Z takimi klasa, możesz mieć:

Set<PersonWrapper> set2 = list2.stream().map(PersonWrapper::wrap).collect(toSet()); 

boolean exists = 
    list1.stream() 
     .map(PersonWrapper::wrap) 
     .filter(set2::contains) 
     .findFirst() 
     .isPresent(); 

System.out.println(exists); 

Ten kod konwertuje list2 w Set osób zawinięte. Celem posiadania Set jest posiadanie stałej operacji contains dla lepszej wydajności.

Następnie filtr list1 jest filtrowany. Każdy element znaleziony w set2 jest zachowany i jeśli pozostało jeszcze element (to znaczy, jeśli findFirst() zwraca niepustą wartość Optional), oznacza to, że element został znaleziony.

+0

w moim przypadku równe nie mogą być przesłonięte – TNN

+4

@TodorNeykov Tak właśnie się domyśliłem i stworzyłem klasę niestandardową z zaimplementowanym 'equals', zobacz moją odpowiedź. – Tunaki

+0

hm ładnie jeden, ale wciąż ciężki .. – TNN

2

Jeśli nie interesuje Cię pole id, możesz użyć metody equals, aby rozwiązać ten problem.

Oto kod Person klasa

public class Person { 
    private String id ; 
    private String name; 
    private String age; 

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

    Person sample = (Person) o; 

    if (!name.equals(sample.name)) return false; 
    return age.equals(sample.age); 

    } 

    @Override 
    public int hashCode() { 
    int result = name.hashCode(); 
    result = 31 * result + age.hashCode(); 
    return result; 
    } 
} 

Teraz można użyć, aby uzyskać strumień skrzyżowanie jak tak. common będzie zawierał wszystkie obiekty Person, gdzie name i age są takie same.

List<Person> common = list1 
     .stream() 
     .filter(list2::contains) 
     .collect(Collectors.toList()); 
+0

w moim przypadku równe nie mogą być nadpisane – TNN

1

to będzie działać:

class PresentOrNot {boolean isPresent = false;}; 
final PresentOrNot isPresent = new PresentOrNot(); 
l1.stream().forEach(p -> { 
    isPresent.isPresent = isPresent.isPresent || l2.stream() 
     .filter(p1 -> p.name.equals(p1.name) && p.age.equals(p1.age)) 
     .findFirst() 
     .isPresent(); 
}); 
System.err.println(isPresent.isPresent); 

Od forEach() trwa konsumenta, nie mamy możliwości zwrotu i PresentOrNot {} to obejście. bok: Gdzie Didi masz takiego wymogu :)

2

brute force, ale czysty Java 8 rozwiązanie będzie to:

boolean present = list1 
     .stream() 
     .flatMap(x -> list2 
      .stream() 
      .filter(y -> x.getName().equals(y.getName())) 
      .filter(y -> x.getAge().equals(y.getAge())) 
      .limit(1)) 
     .findFirst() 
     .isPresent(); 

Tutaj flatmap służy do łączenia 2 list. limit jest używany, ponieważ jesteśmy zainteresowani tylko pierwszym dopasowaniem, w którym to przypadku nie musimy przechodzić dalej.

1
<h3>Find List of Object passing String of Array Using java 8?</h3> 
[Faiz Akram][1] 
    <pre> 
    public class Student { 
     private String name; 
     private Integer age; 
     public Student(String name, Integer age) { 
      super(); 
      this.name = name; 
      this.age = age; 
     } 
     public String getName() { 
      return name; 
     } 
     public void setName(String name) { 
      this.name = name; 
     } 
     public Integer getAge() { 
      return age; 
     } 
     public void setAge(Integer age) { 
      this.age = age; 
     } 
    } 
    </pre> 
    // Main Class 
    <pre> 
    import java.util.ArrayList; 
    import java.util.Arrays; 
    import java.util.List; 
    import java.util.stream.Collectors; 
    public class JavaLamda { 
     public static void main(String[] k) 
     { 
     List<Student> stud = new ArrayList<Student>(); 
     stud.add(new Student("Faiz", 1)); 
     stud.add(new Student("Dubai", 2)); 
     stud.add(new Student("Akram", 5)); 
     stud.add(new Student("Rahul", 3)); 
     String[] name= {"Faiz", "Akram"}; 
     List<Student> present = Arrays.asList(name) 
       .stream() 
       .flatMap(x -> stud 
        .stream() 
        .filter(y -> x.equalsIgnoreCase(y.getName()))) 
       .collect(Collectors.toList()); 
     System.out.println(present); 
     } 
    } 
    </pre> 
    OutPut //[[email protected], [email protected]] 


    [1]: http://faizakram.com/blog/find-list-object-passing-string-array-using-java-8/ 
0
public static void main(String[] args) { 
    OTSQuestions ots = new OTSQuestions(); 

    List<Attr> attrs = ots.getAttrs(); 
    List<String> ids = new ArrayList<>(); 
    ids.add("101"); 
    ids.add("104"); 
    ids.add("102"); 

    List<Attr> finalList = attrs.stream().filter(
      attr -> ids.contains(attr.getId())) 
      .collect(Collectors.toList()); 
} 

public class Attr { 
    private String id; 
    private String name; 

    public String getId() { 
     return id; 
    } 

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

    public String getName() { 
     return name; 
    } 

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

private List<Attr> getAttrs() { 
    List<Attr> attrs = new ArrayList<>(); 
    Attr attr = new Attr(); 
    attr.setId("100"); 
    attr.setName("Yoga"); 
    attrs.add(attr); 

    Attr attr1 = new Attr(); 
    attr1.setId("101"); 
    attr1.setName("Yoga1"); 
    attrs.add(attr1); 

    Attr attr2 = new Attr(); 
    attr2.setId("102"); 
    attr2.setName("Yoga2"); 
    attrs.add(attr2); 

    Attr attr3 = new Attr(); 
    attr3.setId("103"); 
    attr3.setName("Yoga3"); 
    attrs.add(attr3); 

    Attr attr4 = new Attr(); 
    attr4.setId("104"); 
    attr4.setName("Yoga4"); 
    attrs.add(attr4); 

    return attrs; 
} 
Powiązane problemy