2016-06-14 31 views
6

In Anbetracht des folgenden Codes und der Tatsache, dass die 4 HashSet s an anderer Stelle bestückt sind.Wie berechne ich Schnittmengen zwischen mehr als zwei HashSets?

Mein Ziel ist es, alle Elemente zu enthalten, die in allen 4 HashSets üblich sind.

Meine Frage ist zuerst, mache ich es richtig? Zweitens, wenn ich es richtig mache, gibt es einen besseren Weg, es zu tun? Wenn nicht, welche Lösung habe ich für dieses Problem?

static Set<String> one=new HashSet<>(); 
static Set<String> two=new HashSet<>(); 
static Set<String> three=new HashSet<>(); 
static Set<String> four=new HashSet<>(); 

private static void createIntersectionQrels() { 
    ArrayList<String> temp = new ArrayList<>(); 
    Set<String> interQrels = new HashSet<>(); 

    temp.addAll(one); 
    one.retainAll(two); 
    interQrels.addAll(one); 
    one.addAll(temp); 
    one.retainAll(three); 
    interQrels.addAll(one); 
    one.addAll(temp); 
    one.retainAll(four); 
    interQrels.addAll(one); 
    one.addAll(temp); 

    interQrels.retainAll(two); 
    interQrels.retainAll(three); 
    interQrels.retainAll(four); 
} 

Antwort

9

Ich denke, man kann einfach retainAll() auf dem ersten Satz nennen kann, die zweite mit, dritten und vierten Satz als Parameter:

private static Set<String> getIntersectionSet() { 
    // create a deep copy of one (in case you don't wish to modify it) 
    Set<String> interQrels = new HashSet<>(one); 

    interQrels.retainAll(two);  // intersection with two (and one) 
    interQrels.retainAll(three); // intersection with three (and two, one) 
    interQrels.retainAll(four); // intersection four (and three, two, one) 

    return interQrels; 
} 
+0

Also mache ich nur überreagieren, um den ersten Satz jedes Mal zu füllen, wenn ich 'retainAll()' verwende? Ich habe mir nur Sorgen gemacht, dass wenn Informationen verloren gehen. – lonesome

+0

Wenn ein Element wirklich allen vier Sets gemeinsam ist, müssen Sie es nicht hinzufügen (denken Sie einen Moment darüber nach). –

+0

Ja, scheint ungefähr richtig. – lonesome

0

Ich würde denken, der beste Weg, damit umzugehen, ist mit Groovy. Ich weiß, dass du nicht nach Groovy gefragt hast, aber jederzeit, wenn ich den ganzen Code in eine Zeile umwandeln kann, ist es schwer zu widerstehen.

println one.intersect(two).intersect(three).intersect(four) 
3

Ich bin ein bisschen neu in Java 8, aber dies scheint ziemlich lesbar:

Set<String> intersection = one.stream() 
            .filter(two::contains) 
            .filter(three::contains) 
            .filter(four::contains) 
            .collect(Collectors.toSet()); 

Hier ist ein schneller JUnit-Test ist zu versuchen:

@Test 
public void testIntersectionBetweenSets() { 
    Collection<String> one = new HashSet<>(4); 
    one.add("Larry"); 
    one.add("Mark"); 
    one.add("Henry"); 
    one.add("Andrew"); 
    Set<String> two = new HashSet<>(2); 
    two.add("Mark"); 
    two.add("Andrew"); 
    Set<String> three = new HashSet<>(3); 
    three.add("Mark"); 
    three.add("Mary"); 
    three.add("Andrew"); 
    Set<String> four = new HashSet<>(3); 
    four.add("Mark"); 
    four.add("John"); 
    four.add("Andrew"); 

    Set<String> intersection = one.stream() 
      .filter(two::contains) 
      .filter(three::contains) 
      .filter(four::contains) 
      .collect(Collectors.toSet()); 

    Collection<String> expected = new HashSet<>(2); 
    expected.add("Andrew"); 
    expected.add("Mark"); 
    Assert.assertEquals(expected, intersection); 
} 
+0

Nizza - sollte aber über Streams;) +1 – Chewy