2016-06-14 23 views
6

Considerando il codice sottostante e il fatto che i 4 HashSet s sono popolati altrove.Come si calcola l'intersezione tra più di due HashSet?

Il mio obiettivo è quello di contenere tutti gli elementi comuni in tutti e 4 i hash.

La mia domanda è che prima di tutto sto facendo bene? In secondo luogo, se lo sto facendo bene, c'è un modo migliore per farlo? In caso contrario, quale soluzione ho per questo problema?

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); 
} 

risposta

9

Penso che si possa semplicemente possibile chiamare retainAll() sul primo set, utilizzando il secondo, terzo e quarto set come parametri:

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

Quindi sto facendo un eccesso di reazione per popolare il primo set ogni volta che uso 'retainAll()'? Sono solo preoccupato che se alcune informazioni vengono perse. – lonesome

+0

Se un elemento è davvero comune a tutti e quattro i set, non è necessario continuare ad aggiungerlo (pensaci per un momento). –

+0

Sì, sembra giusto. – lonesome

0

Penso che il modo migliore per gestirlo sia con Groovy. So che non hai chiesto di essere groovy, ma ogni volta che posso convertire tutto quel codice in una riga, è difficile resistere.

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

Sono un po 'nuova a Java 8, ma questo sembra abbastanza leggibile:

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

Ecco un test JUnit veloce per provare:

@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

Bello - dovrebbe essere una questione di flussi;) +1 – Chewy

Problemi correlati