Chcę utworzyć kolekcje, które mogą zawierać zduplikowane wartości, w dowolnej kolejności.Jaka kolekcja Java uważa permutacje za równe?
Innymi słowy:
{ 1, 1, 2 } == { 2, 1, 1 } == { 1, 2, 1 }
W rzeczywistości, chcę mieć zestaw tych zbiorów, więc jeśli próbuję dodać zarówno { 1, 1, 2 }
i { 2, 1, 1 }
, drugi .add()
nie będzie właściwie nic.
Czy istnieje standardowa kolekcja, która już działa w ten sposób?
Jeśli dobrze rozumiem:
- ArrayList pozwala na zduplikowane wartości, ale ma ustalony porządek
- HashSet pozwala na celu być dowolna, ale nie zduplikowane wartości
- TreeSet zapewnia, że zamówienie jest stała, ale nie pozwala na powielanie wartości
Czy istnieje kolekcja, którą pominąłem, która pozwala na kopiowanie zarówno wartości dowolnych, jak i stałych kolejności, tak aby dwie kolekcje z tymi samymi elementami były uważane za równe?
@asteri pytanie o mój przypadek użycia. W grze mam klocki o różnych długościach, które można ułożyć do końca, aby wypełnić pewną odległość. Na przykład, jeśli odległość wynosi 10, można ją wypełnić 2-3-5 lub 5-2-3 lub 3-3-4 lub 3-4-3 lub dowolną liczbą innych permutacji. W zależności od tego, jakie bloki są dostępne, chcę utworzyć listę wszystkich możliwych kolekcji, które rozwiążą lukę.
niestandardowe rozwiązania
@sprinter zaproponował utworzenie podklasy ArrayList. @dasblinkenlight i @Dici zasugerowali użycie Map do przechowywania wpisów { Element : Count }
. Postanowiłem połączyć te dwie sugestie. Poniżej znajduje się podklasa TreeMap. Klucze są zawsze przechowywane w tej samej kolejności, aby zapewnić, że metoda hashCode() generuje taką samą wartość dla tych samych kluczy i wartości.
Użyłem metody increment
, aby ułatwić dodanie nowego wystąpienia konkretnej liczby całkowitej "wartość".
package com.example.treematch;
import java.util.Map;
import java.util.TreeMap;
public class TreeMatch<K> extends TreeMap<K, Integer> {
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof TreeMatch)) {
return false;
}
TreeMatch otherMatch = (TreeMatch) other;
if (size() != otherMatch.size()) {
return false;
}
for (Object key : this.keySet()) {
if (!otherMatch.containsKey(key)) {
return false;
}
}
for (Object key : otherMatch.keySet()) {
if (!this.containsKey(key)) {
return false;
}
if (this.get(key) != otherMatch.get(key)) {
return false;
}
}
return true;
}
public void increment(K key) {
Integer value;
if (this.containsKey(key)) {
value = (this.get(key)) + 1;
} else {
value = 1;
}
this.put(key, value);
}
@Override
public int hashCode() {
int hashCode = 0;
for (Map.Entry entry : this.entrySet()) {
hashCode += entry.getKey().hashCode();
hashCode = hashCode << 1;
hashCode += entry.getValue().hashCode();
hashCode = hashCode << 1;
}
return hashCode;
}
}
Mmm ... ciekawe pytanie. Nie o tym myślę, choć może być coś, co pomaga w Apache Commons lub Guava. Czy z ciekawości mogę spytać o twój przypadek użycia? – asteri
Nie jest to odpowiedź na twoje pytanie, ale łatwym obejściem byłoby posiadanie ich jako list, a następnie posortowanie ich i porównanie. – asteri
Interesujące: [Czy istnieje sposób sprawdzenia, czy dwie kolekcje zawierają te same elementy, niezależnie od kolejności?] (Http://stackoverflow.com/a/1565262/1762224) '->' 'HashMultiset.create (c1). equals (HashMultiset.create (c2)); ' –