java 8 i odwołanie jak po wskaźniku w C do elementu w tablicy

0

Cześć. Jak zrobić w java taką operacje? Chcę wrzucać do tablicy HashSet powtarzające się indeksy, i jeśli ten indeks jest już w tablicy, to żeby pobrał wartość, zwiększył o 1, czyli coś takiego

public class Main
{
    private Map<Double,Integer> arr = new HashMap<Double,Integer>();
    
    public static void main(String[] args) 
    {
        for (Map.Entry<Double,Integer> entry : arr.entrySet()) {
            double key = entry.getKey();
            int val = entry.getValue();
            // załóżmy że jest już w tablicy indeks o numerze 10
            // pierwszy element jeśli go tam nie ma jest z wartością 0
            if (key == 10) {
                key.replace(key, val++);
            } else {
                arr.put(key, 0);
            }
        }    
    }
}

W C można po prostu użyć wskaźnika żeby odwołać się bezpośrednio pod adres konkretnego elementu, ale jak zrobić coś podobnego w javie, żeby przy powtórzeniu się elementu, zwiększyć tylko licznik który ma liczyć ile tych powtarzających się elementów jest?

1

Co do wrzucania do mapy zwiększonej wartości jeśli dany klucz istnieje potrzebujesz użyć metody computeIfPresent() :
https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#computeIfPresent-K-java.util.function.BiFunction-

1

Absolutnie nie kumam co mają do tego wskażniki.
Ale to czego szukasz to pewnie operacja merge w hashmap

map.merge(key, 0, (old, newVal) -> old+ 1); 

0 (swoją drogą dziwne) - jeśli elementu nie było, lamba odpowiada za zwiększanie o jeden za każdym kolejnym razem (jeśli element był)
newVal jest ignorowany tutaj (ale chyba w javie nie ma jak wyrazić ignorowania ( _) )

Z drugiej strony Double jako klucz zwykle się nie sprawdza. Jeśli to Double pochodzi z obliczeń to w wyniku błędów zaokrągleń będziesz miał wiele bliskich, ale formalnie różnych wartości:
np. 2.000000000000000000 i 2.0000000000000000001

0

computeIfPresent pomogło. Właśnie tego szukałem. Po prostu ze wskaźnikami jak w C jest prościej bo się bezpośrednio odwołujesz i możesz potem zwiększyć wartośc i z powrotem zapisać pod ten sam adres, a w java nie bardzo wiem jak tak do tego podejść.

Jeszcze sprawdzę to merge.
// e. merge też działa
Dzięki,

import java.util.*;

public class Main
{
    private static Map<Double,Integer> arr = new HashMap<Double,Integer>();
    
    public static void main(String[] args) 
    {
    
        arr.put(10.0,1);
        
         arr.computeIfPresent(10.0, (k , v)  -> v + 100); 
         arr.merge(10.0, 0, (old, newVal) -> old+ 1); 
    
        for (Map.Entry<Double,Integer> entry : arr.entrySet()) {
            double key = entry.getKey();
            int val = entry.getValue();        
            System.out.println(key + " " + val);
        }    
    }
}
0

W javie też są tablice.
W zasadzie słowo też jest nieadekwatne - w javie naprawde są tablice, w C nie ma - jest tam tylko gniot na wskaźnikach.
Z drugiej strony raczej się ich w normalnych programach nie używa ( i słusznie).

0
jarekr000000 napisał(a):

W javie też są tablice.
W zasadzie słowo też jest nieadekwatne - w javie naprawde są tablice, w C nie ma - jest tam tylko gniot na wskaźnikach.
Z drugiej strony raczej się ich w normalnych programach nie używa ( i słusznie).

Dobrze byłoby kiedyś zajrzeć pod spód. Jakiś czas temu po obejrzeniu tego nagrania 36:28 próbowałem zainstalować ten toolchain https://github.com/liuzhengyang/hsdis ?! To coś do zrzutu do asemblera. Ale nie poszło. Może kiedyś to ujarzmię. Ale dobrze byłoby kiedyś zobaczyć te wszystkie tablice hash, set, map, albo int[][] i operacje na nich w asemblerze.

0
shab napisał(a):

Dobrze byłoby kiedyś zajrzeć pod spód.

Ło panie :-) To nie ma nic wspólnego z C, tablicami itd.

Jakbyś miał problem z -XX:+PrintAssembly (hsdis) to:

0
jarekr000000 napisał(a):
shab napisał(a):
  • ewentualnie napisz jaki masz problem - mam to mam ogarnięte na różnych linuksach i windows (nie macos)

Właśnie już dostałem od Was odpowiedź wyżej. Potrzebuję zrobić statystyki, akurat wymyśliłem że użyję do tego tablic hash które w przeciwieństwie do np List, które nie mają żadnych ograniczeń, tylko jeśli dany indeks już istnieje odrzucają go (odrzucają czy nadpisują bo serio, teraz nie wiem dokładnie jak to działa ?!), ewentualnie można coś z nim zrobić. Chciałem zrobić w ten sposób statystykę kilku rzeczy, na przykład obliczyć częstostliość pewnej wartości w danym okresie czasu, czyli wygląda to mniej więcej tak. Nie wiem czy jasno to wyjaśniłem.

Date dane = new Date(System.currentTimeMillis);
...
if (date.getHours().equals(key)) {
// system ma zliczać powtarzające się dane 
// czyli jeśli w danej godzinie pewna wartość się powtarza 
// ma zwiększać licznik, czyli mam policzyć statystykę najczęsciej pojawiających się godzin (wartości) 
// w/w określonych warunkach.  Ok, założmy że o 17 pojawiła się kilka razy ta sama wartość w
// w przeciągu kilku dni/tygodni, system właśnie ma to podliczyć, czyli inkremetnować wartość
// żeby uzyskać na końcu statysytkę według podziału na godziny. Powiedzmy że  w środę i piątrek 
// w tym tygodniu o 17 pojawiła się wartość 20, więc licznik dla 17 powinien wynosić 2, dla innych godzin
// w zależności od tego ile dana wartość wystąpiła. Coś takiego. 
// I w sumie problem już jest rozwiązany bo merge i computeIfPresent to liczy 
}
0

Czyli robisz coś w stylu histogramu.
HashMapa jest do tego ok.

Masz też specjalne biblioteki do tego https://commons.apache.org/proper/commons-math/userguide/stat.html#a1.3_Frequency_distributions
(pierwsza z brzegu)

Hashmapa robi co jej każesz,
Metoda put nadpisze wartość
putIfAbsent dopisze nową jeśli nie było
merge daje możliwość jednocześnie wstawienia nowej wartości jeśli wcześniej nic nie było, jak też recepty jak tą wartość zmienić jak już coś jest pod kluczem (np. inkrementować),
i jest jeszcze kilka innych metod.

0
jarekr000000 napisał(a):

moje dopytanie było do hsdis To coś do zrzutu do asemblera. Ale nie poszło

Sorki, będzie trochę długi opis :)

Mam ten sam problem ze zbudowaniem tego komendą make BINUTILS=binutils-2.26 ARCH=amd64 co tutaj na stackoverflow https://stackoverflow.com/questions/52737698/unable-to-compile-unrecognized-relocation-0x2a-in-section-text

Wypluwa mi dokładnie to samo

/usr/bin/ld: build/linux-amd64/bfd/libbfd.a(archures.o): unrecognized relocation (0x2a) in section `.text'
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
make: *** [build/linux-amd64/hsdis-amd64.so] Error 1

Patrzę niżej w opisie instalacji hsdis że było to kompilowane na Ubuntu 16.04, a ja mam 14.04LTS. To już nie pierwszy taki przypadek kiedy mam problem z instalacją niektórego softu właśnie przez starą dystrybuję, problemy niezgodności ale dobra.

Następnie sprawdzam według porady jaką mam wersję ld -- version

GNU ld (GNU Binutils for Ubuntu) 2.24
Copyright 2013 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

Próbowałem robić upgrade sudo apt-get install --reinstall binutils ale dalej zostaje 2.24

Więc dałem sobie z tym spokój i zbudowałem to takim poleceniem make BINUTILS=binutils-2.26 ARCH=Linux i poszło.

Następnie przeniosłem ten plik hsdis-linux.so do /usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/amd64/server bo chyba to jest właściwa ścieżka, skoro mam do wyboru w /usr/lib/jvm
jshot.png

Więc mam plik hsdis-linux.so w lokalizacji /usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/amd64/server

Następnie robię hello world w java i kompiluję javac -g Main.java

public class Main
{
	public static void main(String[] args) {
		System.out.println(1);
	}
}	

I odpalam java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -Xcomp -XX:CompileCommand=compileonly,Main.main Main . Dostaję wtedy taki komunikat

OpenJDK 64-Bit Server VM warning: PrintAssembly is enabled; turning on DebugNonSafepoints to gain additional output
CompilerOracle: compileonly Main.main
Could not load hsdis-amd64.so; library not loadable; PrintAssembly is disabled
1

Czyli szuka hsdis-amd64.so, ale nie dałem rady właśnie tego skompilować przez te problemy o których pisałem wyżej.

Jeszcze robię java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -Xcomp -XX:CompileCommand=compileonly,Main Main to wyrzuca to, potem chwilę coś tam robi i zwraca 1

OpenJDK 64-Bit Server VM warning: PrintAssembly is enabled; turning on DebugNonSafepoints to gain additional output
CompilerOracle: unrecognized line
  "compileonly Main"
  Unrecognized text  Main after command 
Could not load hsdis-amd64.so; library not loadable; PrintAssembly is disabled
1

Więc reasumując, albo jakoś trzeba zrobić upgrade ld z 2.24 do 2.26, ale nie wiem jak, albo jeszcze coś żeby to poszło z polecenia make BINUTILS=binutils-2.26 ARCH=amd64

0

Hmmm - nie wiem co zrobić, ale masz takie opcje:

0

Spróbowałem zmienić po prostu nazwę i zaczęło coś wyrzucać ale wolało po śledzeniu strace że to nie jest zbudowane pod tą achitekturę co trzeba, wypluło też jakieś wyniki ale nie pokazywało asemblera bo nie mogło go określić. A teraz zobaczyłem że w reposytorium jest ten plik hsdis-amd64.so https://github.com/liuzhengyang/hsdis/blob/master/build/linux-amd64/hsdis-amd64.so i to wstawiłem do tej ścieżki co miała być i kurde działa :)

java -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining -XX:+PrintAssembly -XX:PrintAssemblyOptions=intel -XX:CompileCommand=print, Main Main

Chociaż jak patrzę wstępnie w ten kod, patrzę na każdą sekcje [Entry Point] i porównuję z tym co zwraca javap -c Main to na razie nie kumam jak to działa i co z tego można wyczytać.

W każdym razie dzięki wielkie za pomoc. Udało się rozwiązać oba problemy hihi.

1

Przy prostym programie typu HelloWorld niewiele zobaczysz - bo sam program się nie skompiluje.
Napisz jakąś metodę - odpal ją 20000 razy w pętli i wtedy powinieneś dostać kod.zmieniająć(-XX:CompileCommand=print,*MyClass.myMethod), można też ten parametr wywalić i po prostu zostać zalanym assemblerem, ale da się kod wyszukać.
Jakkolwiek - jak pisałem wyżej niewiele z tego się da wyciągnąć nawet jak znasz asm.

1 użytkowników online, w tym zalogowanych: 0, gości: 1