Jestem nowy w Javie i bardzo zdezorientowany.
Mam duży zbiór danych o długości 4 int[]
i chcę policzyć, ile razy występuje każda określona kombinacja 4 liczb całkowitych. Jest to bardzo podobne do liczenia częstości występowania słów w dokumencie.
Chcę utworzyć Map<int[], double>
odwzorowanie każdego int [] na bieżącą liczbę, gdy lista jest iterowana, ale Map nie przyjmuje typów pierwotnych.
więc zrobiłem Map<Integer[], Double>
moje dane są przechowywane jako, ArrayList<int[]>
więc moja pętla powinna wyglądać jak
ArrayList<int[]> data = ... // load a dataset`
Map<Integer[], Double> frequencies = new HashMap<Integer[], Double>();
for(int[] q : data) {
// **DO SOMETHING TO convert q from int[] to Integer[] so I can put it in the map
if(frequencies.containsKey(q)) {
frequencies.put(q, tfs.get(q) + p);
} else {
frequencies.put(q, p);
}
}
Nie jestem pewien, jakiego kodu potrzebuję w komentarzu, aby przekonwertować plik int[]
an Integer[]
. A może zasadniczo nie mam pojęcia, jak to zrobić.
java
arrays
generics
collections
Jonik
źródło
źródło
Odpowiedzi:
Natywna Java 8 (jeden wiersz)
Dzięki Java 8
int[]
można łatwo przekonwertować naInteger[]
:Jak powiedzieli inni,
Integer[]
zwykle nie jest to dobry klucz do mapy. Ale jeśli chodzi o konwersję, mamy teraz stosunkowo czysty i natywny kod.źródło
List<Integer> list = IntStream.of(q).boxed().collect(Collectors.toList());
Integer[]
sugerowałbym użycie następującej składni:Integer[] boxed = IntStream.of(unboxed).boxed().toArray();
W podobny sposób jak @NwDxIntStream.of
dzwoniArrays.stream
. Myślę, że sprowadza się to do osobistych preferencji - wolę jedną nadpisaną funkcję, niektórzy uwielbiają używać bardziej wyraźnych klas.the "new" method (constructor) of the Integer[] class
.Jeśli chcesz przekonwertować an
int[]
na anInteger[]
, nie ma zautomatyzowanego sposobu, aby to zrobić w JDK. Możesz jednak zrobić coś takiego:Jeśli masz dostęp do biblioteki języka Apache , możesz użyć następującej
ArrayUtils.toObject(int[])
metody:źródło
value
gdyi
jest tam zmienna indeksująca .for (int i...)
tym przypadku bardziej wydajna byłaby tradycyjna pętla.Prawdopodobnie chcesz, aby klucz do mapy pasował do wartości elementów, a nie tożsamości tablicy. W takim przypadku potrzebujesz jakiegoś obiektu, który definiuje
equals
ihashCode
tak jak byś oczekiwał. Najłatwiej jest przekonwertować na aList<Integer>
, alboArrayList
lepiej użyćArrays.asList
. Lepiej niż to, że możesz wprowadzić klasę, która reprezentuje dane (podobnie do,java.awt.Rectangle
ale zalecam, aby zmienne były prywatne jako ostateczne, a klasa także jako ostateczna).źródło
Używanie zwykłej pętli for bez zewnętrznych bibliotek:
Konwertuj int [] na liczbę całkowitą []:
Konwertuj liczbę całkowitą [] na liczbę całkowitą []:
źródło
Myliłem się w poprzedniej odpowiedzi. Właściwym rozwiązaniem jest użycie tej klasy jako klucza w mapie opakowującej rzeczywisty int [].
i zmień swój kod w ten sposób:
źródło
Konwertuj int [] na liczbę całkowitą []
Konwertuj liczbę całkowitą [] na liczbę całkowitą []
źródło
newArray[i] = ids[i];
aw drugimnewArray[i] = WrapperArray[i]
:)Zamiast pisać własny kod możesz użyć IntBuffer do zawijania istniejącego int [] bez konieczności kopiowania danych do tablicy Integer
IntBuffer implementuje porównywalne, więc możesz użyć kodu, który już napisałeś. Formalnie mapy porównują klucze w taki sposób, że a.equals (b) jest używane do stwierdzenia, że dwa klucze są równe, więc dwa IntBuffers z tablicą 1, 2, 3 - nawet jeśli tablice znajdują się w różnych lokalizacjach pamięci - mówi się, że są równe i tak będzie pracować dla twojego kodu częstotliwości.
}
Mam nadzieję, że to pomoże
źródło
Nie wiem, dlaczego potrzebujesz Double na swojej mapie. Jeśli chodzi o to, co próbujesz zrobić, masz int [] i chcesz po prostu policzyć, ile razy występuje każda sekwencja? Dlaczego to i tak wymagało Double?
To, co bym zrobił, to utworzenie opakowania dla tablicy int z odpowiednimi metodami .equals i .hashCode, aby uwzględnić fakt, że sam obiekt int [] nie bierze pod uwagę danych w swojej wersji tych metod.
Następnie użyj multisetu google guava, który jest przeznaczony dokładnie do zliczania wystąpień, o ile typ elementu, który w nim wstawisz, ma odpowiednie metody .equals i .hashCode.
Następnie, aby uzyskać liczbę dla określonej kombinacji:
źródło
IntArrayWrapper
zdecydowanie właściwe podejście do używaniaint[]
tablicy jako klucza mieszającego, ale należy wspomnieć, że taki typ już istnieje … Możesz go użyć do zawijania tablicy i nie tylko ją ma,hashCode
aequals
nawet jest porównywalny.Aktualizacja: Chociaż poniżej kompiluje się, rzuca
ArrayStoreException
w czasie wykonywania. Szkoda. Zostawię to na przyszłość.Konwersja an
int[]
, do anInteger[]
:Muszę przyznać, że byłem trochę zaskoczony, że to się kompiluje, biorąc
System.arraycopy
pod uwagę niski poziom i wszystko, ale tak się dzieje. Przynajmniej w java7.Możesz równie łatwo dokonać konwersji w drugą stronę.
źródło
To zadziałało jak urok!
źródło
Konwertuj int [] na liczbę całkowitą []:
źródło
nie potrzebujesz.
int[]
jest obiektem i może być używany jako klucz wewnątrz mapy.jest poprawnym określeniem mapy częstotliwości.
To było złe :-). Odpowiednie rozwiązanie też jest zamieszczone :-).
źródło
frequencies.containsKey(q)
że zawsze będzie fałszywe, nawet jeśli mamput
dwa razy tę samą tablicę - czy jest tu jakiś błąd dotyczący definicji równości w Javie z int []?Po prostu użyj:
źródło