Discussion:
HashMap wie String[] statisch initialisieren
(zu alt für eine Antwort)
Manfred Pruntsch
2003-10-13 10:27:51 UTC
Permalink
Hi,

gibt es eine Möglichkeit HashMaps ähnlich wie String[] zu initialisieren:
String[] fooString = new String[]{"a", "b"};

HashMap fooHashMap = new HashMap(){"key1","a"; "key2","b"};

In PHP gibt eine Möglichkeit assoziative Arrays ungefähr so zu
initialisieren:
fooArray = {"key1"=>"a", "key2"=>"b"};

regards
Manfred
Jochen Theodorou
2003-10-13 10:44:14 UTC
Permalink
Post by Manfred Pruntsch
Hi,
String[] fooString = new String[]{"a", "b"};
HashMap fooHashMap = new HashMap(){"key1","a"; "key2","b"};
In PHP gibt eine Möglichkeit assoziative Arrays ungefähr so zu
fooArray = {"key1"=>"a", "key2"=>"b"};
public class ArrayinitHashMap extends HashMap() {
public StringHashMap(Object[]keysAndValues) {
super(keysAndValues.length);
int length = 2*(keysAndValues.length/2);
for (int i=0; i<length; i+=2;) {
put(keysAndValues[i],keysAndValues[i+1]);
}
}
}

Du Anwendung erfoglt dann mit:

HashMap fooHash = new ArrayinitHashMap(new String[]{"key1","a",
"key2","b"});

oder das Array extra initialisieren und dann übergeben. Es ist
allerdings lange nicht so übersichtlich wie in PHP.

Gruss theo
Oliver Ramroth
2003-10-13 10:56:45 UTC
Permalink
Servus,
Post by Jochen Theodorou
int length = 2*(keysAndValues.length/2);
kannst Du mir die Anweisung mal erklären? Ich verstehe den Hintergrund nicht.
Aber muß nicht immer eine gerade Anzahl an Elementen übergeben werden?
Sollte man nicht im Falle der falschen Parameterzahl eine Exception schmeissen?

Fragen über Fragen,
Oliver
Jochen Theodorou
2003-10-13 14:15:55 UTC
Permalink
Post by Oliver Ramroth
Servus,
Post by Jochen Theodorou
int length = 2*(keysAndValues.length/2);
kannst Du mir die Anweisung mal erklären? Ich verstehe den Hintergrund nicht.
Aber muß nicht immer eine gerade Anzahl an Elementen übergeben werden?
Sollte man nicht im Falle der falschen Parameterzahl eine Exception schmeissen?
Ach weisst du ich schmeise Exceptions nur dann, wenn ich davon überzeugt
bin, dass es etwas bringt. In diesem Fall hast du natürlich recht. Ich
habe das nur kurz so geschrieben und eigentlich nicht nachgedacht. Und
wenn ich sowas tue falle ich in die Zeiten von Pascal zurück, wo es
keine Exceptions gab. Die kommen bei mir immer erst in eienr 2.
Iteration zustande.
Man könnte sagen, dass Keys ohne Value automatisch auf null gemappt
werden. Da man solche Keys aber eigentlich nicht in eine Hashmap rein
tut, es sei denn man will was überschrieben, ist die Wahrscheinlichkeit
hoch, dass das ein Fehler ist. Vorallem weil so nur der letzte Wert auf
null gemappt wird und die anderen wenn, wenn man es explizit angibt.
Also sollte auf jeden Fall eine Exception geworfen werden.
Die Lösung von Oliver Schoeherr finde ich da gut.

Gruss theo
Andree Große
2003-10-13 15:28:20 UTC
Permalink
Post by Jochen Theodorou
Post by Oliver Ramroth
Servus,
Post by Jochen Theodorou
int length = 2*(keysAndValues.length/2);
kannst Du mir die Anweisung mal erklären? Ich verstehe den Hintergrund nicht.
Ach weisst du ich schmeise Exceptions nur dann, wenn ich davon überzeugt
...
Dennoch bleibt wohl:

int x = 2 * y / 2 = 2 * y * 1/2;
x = 2 / 2 * y = 2 * 1/2 * y;
x = 1 * y;
x = y;

Oder?
A.G.
Sönke Müller-Lund
2003-10-13 15:43:55 UTC
Permalink
Moin Andree,
Post by Andree Große
int x = 2 * y / 2 = 2 * y * 1/2;
Nur für y=0, denn die rechte Seite ist stets 0.
Post by Andree Große
x = y;
Ist trotzdem für alle |y| < Integer.MAXINT/2 richtig, da 2*y zuerst
ausgeführt wird.

Sönke
Andree Große
2003-10-14 07:51:50 UTC
Permalink
Post by Sönke Müller-Lund
Moin Andree,
Post by Andree Große
int x = 2 * y / 2 = 2 * y * 1/2;
Nur für y=0, denn die rechte Seite ist stets 0.
???
Wenn die rechte Seite stets 0 ist, dann ist das Array
also stets leer und die Berechnung wird so noch unsinniger,
als sie es ohnhehin schon ist. Möchtest du die Aussage,
das die rechte Seite stets 0 ist mal über vollständige
Induktion beweisen? Wir reden doch hier über natürliche
ganze positive Zahlen - Oder?
Post by Sönke Müller-Lund
Ist trotzdem für alle |y| < Integer.MAXINT/2 richtig, da 2*y zuerst
ausgeführt wird.
Du wolltest was mit Modulo 2 machen und es einfach
nicht zugeben. Es ist völlig Wurscht, ob ich erst dividiere
und dann multipliziere oder umgekehrt - das Ergebnis
ist das selbe. Du halbierst die Arraylänge um sie
danach wieder mit 2 zu multiplizieren. Du glaubst
vermutlich, dass sich die CPU sonst langweilt.

A.G.
und komm jetzt nicht mit implizitem Casting etc.
Sönke Müller-Lund
2003-10-14 08:39:53 UTC
Permalink
Moin Andree,
Post by Andree Große
Post by Sönke Müller-Lund
Post by Andree Große
int x = 2 * y / 2 = 2 * y * 1/2;
Nur für y=0, denn die rechte Seite ist stets 0.
???
Wenn die rechte Seite stets 0 ist, dann ist das Array
also stets leer und die Berechnung wird so noch unsinniger,
als sie es ohnhehin schon ist. Möchtest du die Aussage,
das die rechte Seite stets 0 ist mal über vollständige
Induktion beweisen? Wir reden doch hier über natürliche
ganze positive Zahlen - Oder?
Ich habe mich von deiner Schreibweise blenden lassen. Wie wir wissen,
gilt in Java 1/2 == 0, aber das steht oben so nicht da.

Sorry.
Post by Andree Große
Post by Sönke Müller-Lund
Ist trotzdem für alle |y| < Integer.MAXINT/2 richtig, da 2*y zuerst
ausgeführt wird.
Du wolltest was mit Modulo 2 machen und es einfach
nicht zugeben. Es ist völlig Wurscht, ob ich erst dividiere
und dann multipliziere oder umgekehrt
Überzeuge dich selbst:

public class OverflowTest {

public static boolean belongsToPriority(int n) {
return 2 * n / 2 != n;
}

public static void main(String[] args) {
System.out.println(belongsToPriority(Integer.MAX_VALUE / 2));
System.out.println(belongsToPriority(Integer.MAX_VALUE / 2 + 1));
System.out.println(belongsToPriority(-Integer.MAX_VALUE / 2));
System.out.println(belongsToPriority(-Integer.MAX_VALUE / 2 - 1));
}
}

Ooops!

Sönke
Jochen Theodorou
2003-10-14 12:24:48 UTC
Permalink
Post by Andree Große
Post by Oliver Ramroth
Servus,
Post by Jochen Theodorou
int length = 2*(keysAndValues.length/2);
kannst Du mir die Anweisung mal erklären? Ich verstehe den
Hintergrund nicht.
[...]
Post by Andree Große
int x = 2 * y / 2 = 2 * y * 1/2;
x = 2 / 2 * y = 2 * 1/2 * y;
x = 1 * y;
x = y;
Oder?
nicht bei Integerarithmentik.

angenommen n=2*m
dann folgt n/2=m
angenommen n=2*m+1
dann folgt n/2=m + .5
Da Integers kein .5 kennen wird daraus m. dh.
m=n/2 egal ob n=2*m+1 oder n=2*m
Daraus folgt: 2*(n/2)=2*m

Sicherlich wäre ein:
if (n%2=1) n--;

besser gewesen. Wenn man jetzt meine Lösung oben so schreibt:
(n>>2)<<2
sind das genau 2 Maschinenbefehle und 2 Takte. Bei i386 Assembler kenne
ich modulo nur als Nebenprodukt von div das mehr als einen Takt
verbraucht. Auserdem kommen dann noch ein Sprung und ein dec hinzu. Man
könnte vom Compiler erwarten dass er das bei mal 2 und dividiert durch 2
erkennt und in shift wandelt. Also ist meine Variante nicht eine um die
CPU zu beschäftigen ;)
Aber da wir hier in Java sind... egal.

Wie in den anderen Postings geschrieben ist es garnicht sinnvoll
gewesen. Es ist besser zu prüfen, ob die länge gerade ist und wenn nicht
eine Exception zu werfen.

Gruss theo
Oliver Schoenherr
2003-10-13 11:47:46 UTC
Permalink
Hallo Jochen,
Post by Jochen Theodorou
public class ArrayinitHashMap extends HashMap() {
public StringHashMap(Object[]keysAndValues) {
super(keysAndValues.length);
int length = 2*(keysAndValues.length/2);
for (int i=0; i<length; i+=2;) {
put(keysAndValues[i],keysAndValues[i+1]);
}
}
}
ich wuerde in diesem Fall nicht ableiten. Eine Art Factory
ermoeglicht es dir alle Map-Implementierungen zu fuellen, nicht nur eine
HashMap:

public class MapUtils {

public static Map fill(Map map, Object[] keysAndValues) {

if ((keysAndValues.length % 2) != 0) {
throw new IllegalArgumentException("Keys and values must be
arranged in pairs");
}
for (int i = 0; i < keysAndValues.length; i += 2) {
map.put(keysAndValues[i], keysAndValues[i + 1]);
}

return map;
}

public static void main(String[] args) {

Hashtable map = (Hashtable) MapUtils.fill(new Hashtable(),new
String[]{"key","value","key2","value2"});

}
}

Oliver
Stefan Matthias Aust
2003-10-13 13:22:03 UTC
Permalink
Post by Manfred Pruntsch
String[] fooString = new String[]{"a", "b"};
Das ist übrigens auch keine statische Initialisierung sondern nur eine
Kurzform für

String[] fooString = new String[2];
fooString[0] = "a";
fooString[1] = "b";

und bei jedem Durchlaufen des Codes wird ein neues Array mit zwei neuen
Stringliteralen aufgebaut.


bye
--
Stefan Matthias Aust // "Ist es normal, nur weil alle es tun?" -F4
Sven Köhler
2003-10-13 15:02:13 UTC
Permalink
Post by Stefan Matthias Aust
Post by Manfred Pruntsch
String[] fooString = new String[]{"a", "b"};
Das ist übrigens auch keine statische Initialisierung sondern nur eine
Kurzform für
String[] fooString = new String[2];
fooString[0] = "a";
fooString[1] = "b";
und bei jedem Durchlaufen des Codes wird ein neues Array mit zwei neuen
Stringliteralen aufgebaut.
... wie der new-operator ja auch vermuten lässt.
obwohl man natürlich auch eine statische kopie davon jedesmal kopieren
könnte - allerdings wäre das etwas verwirrend, zumal man immer etwas
mehr speicher reserviert hätte als nötig.
Paul Ebermann
2003-10-13 23:19:25 UTC
Permalink
Post by Stefan Matthias Aust
String[] fooString = new String[2];
fooString[0] = "a";
fooString[1] = "b";
und bei jedem Durchlaufen des Codes wird ein neues Array mit zwei neuen
Stringliteralen aufgebaut.
Wobei die Stringliterale nur sehr eingeschränkt
neu sind ...


SCNR
Paul
Sven Köhler
2003-10-13 15:04:16 UTC
Permalink
Post by Manfred Pruntsch
String[] fooString = new String[]{"a", "b"};
nein, da musst du eine schleife bauen, oder eine fertige HashMap
irgentwie abspeichern.
Post by Manfred Pruntsch
In PHP gibt eine Möglichkeit assoziative Arrays ungefähr so zu
fooArray = {"key1"=>"a", "key2"=>"b"};
PHP ist eine Scriptsprache.
Du vergleichst hier Äpfel mit Birnen.
Joachim Karrer
2003-10-13 16:40:26 UTC
Permalink
Post by Sven Köhler
Post by Manfred Pruntsch
String[] fooString = new String[]{"a", "b"};
nein, da musst du eine schleife bauen, oder eine fertige HashMap
irgentwie abspeichern.
"Abspeichern", s. hierzu: Properties.load(), Properties.save()

(z.B. als Stream mit einem "StringBufferInputStream" aus einem String
auslesbar...
*aua* nicht hauen...
nein, Kinder, macht sowas nicht daheim nach... die o.g. Klasse ist böse und
deprecated weil sie nicht ordentlich konvertieren [1] kann.
Mich wundert allerdings, dass es noch kein "Properties.load(Reader)" und das
passende Gegenstück gibt... immer muss man alles selber machen, echt blöd.)
Post by Sven Köhler
Post by Manfred Pruntsch
In PHP gibt eine Möglichkeit assoziative Arrays ungefähr so zu
fooArray = {"key1"=>"a", "key2"=>"b"};
PHP ist eine Scriptsprache.
Du vergleichst hier Äpfel mit Birnen.
Aber schön wär's manchmal doch... (auch wenn man's nicht wirklich braucht
bzw. die Zuweisungen "selbstprogrammiert" effizienter gestalten kann.)

Ich hoffe bloss, dass hier in nächster Zeit keiner auf die Idee kommt und
fragt, warum 'foo["superHash"]="gehtnicht"' nicht von Java unterstützt
wird...

Gruss
Joachim

[1] protestantisch<->katholisch
Patrick Roemer
2003-10-13 18:21:46 UTC
Permalink
Hallo,
Post by Joachim Karrer
Mich wundert allerdings, dass es noch kein "Properties.load(Reader)" und das
passende Gegenstück gibt... immer muss man alles selber machen, echt blöd.)
Das gibt es aus gutem Grund nicht, weil ein Reader ggfs. mit dem Inhalt
eines Properties-Streams nicht klarkommt:

| When saving properties to a stream or loading them from a stream, the
| ISO 8859-1 character encoding is used. For characters that cannot be
| directly represented in this encoding, Unicode escapes are used; [...]
(Properties API-Doc)

Viele Gruesse,
Patrick
Joachim Karrer
2003-10-13 19:26:35 UTC
Permalink
Post by Patrick Roemer
Hallo,
Post by Joachim Karrer
Mich wundert allerdings, dass es noch kein "Properties.load(Reader)" und
das passende Gegenstück gibt... immer muss man alles selber machen, echt
blöd.)
Das gibt es aus gutem Grund nicht, weil ein Reader ggfs. mit dem Inhalt
| When saving properties to a stream or loading them from a stream, the
| ISO 8859-1 character encoding is used. For characters that cannot be
| directly represented in this encoding, Unicode escapes are used; [...]
(Properties API-Doc)
Mit allen Problemen die dabei auftauchen:

| "[...]however, only a single 'u' character is allowed in an escape
| sequence. The native2ascii tool can be used to convert property files to
| and from other character encodings."

Aua... das schreit nach "deprecation" (sprich, diese Klasse gehört
deprecated) und nach Einführen einer Properties-Klasse, welche mit dem
(neueren/anderen) Konzept der Reader/Writer arbeitet.

aber: immer muss man alles selber machen.
man könnte ja Properties ableiten und neue load/store bauen, die dann aus
einem Reader heraus parsen und in einen Writer schreiben kann...

aber warum ist das parsen keine eigene Methode, z.B. "putLine ( String u );"
mit u einem String mit "=" in der Mitte und alle Leerzeilen und Kommentare
ignoriert. wäre doch auch nicht schlecht, wenn man mit
"(Properties)p.putLine("Ich=binDoof");" setzen könnte und das automatisch
geparsed würde... Code-reuse at its best...

oder sowas (setProperty(), getProperty(), putLine(), propertyNames()) in
einer (evtl. abstrakten) "Properties"-Klasse, die load und save weder
spezifiziert noch implementiert...
load, save und list dann über eine Util-Klasse statisch... (als
loadFromInputStream( Properties p, InputStream is), loadFromReader (
Properties p, Reader r), saveToWriter/listToWriter ( Writer w)...)

Dann wär aber wieder kaum ein signifikanter Unterschied zur Hashtable...
(bis auf die "genormten/gestringten" Keys...)

naja... anscheinend erwarte ich echt zu viel...

Ist halt auch echt blöd, wenn sowas so lange dabei sein muss... und es ist
ja nicht gerade eine unwichtige Klasse... (s. System.properties)

Gruss
Joachim
Dirk Dittert
2003-10-14 09:17:33 UTC
Permalink
Post by Joachim Karrer
aber warum ist das parsen keine eigene Methode, z.B. "putLine ( String u );"
mit u einem String mit "=" in der Mitte und alle Leerzeilen und Kommentare
ignoriert. wäre doch auch nicht schlecht, wenn man mit
"(Properties)p.putLine("Ich=binDoof");" setzen könnte und das automatisch
geparsed würde... Code-reuse at its best...
Das funktioniert aber doch nur bei einzeiligen Properties. Wenn man sich
sein eigenes (auf einem Reader basiertes) load baut, müsste man also
immer noch prüfen, ob man nicht noch die nächste Zeile noch lesen muß.
Damit hat man das Parsen der Zeile doch wieder an zwei Stellen.

Viele Grüße,

Dirk Dittert
Joachim Karrer
2003-10-14 10:49:49 UTC
Permalink
Post by Dirk Dittert
Post by Joachim Karrer
aber warum ist das parsen keine eigene Methode, z.B. "putLine ( String u
);" mit u einem String mit "=" in der Mitte und alle Leerzeilen und
Kommentare ignoriert. wäre doch auch nicht schlecht, wenn man mit
"(Properties)p.putLine("Ich=binDoof");" setzen könnte und das automatisch
geparsed würde... Code-reuse at its best...
Das funktioniert aber doch nur bei einzeiligen Properties. Wenn man sich
sein eigenes (auf einem Reader basiertes) load baut, müsste man also
immer noch prüfen, ob man nicht noch die nächste Zeile noch lesen muß.
Damit hat man das Parsen der Zeile doch wieder an zwei Stellen.
... hab mir gestern mal noch den Source von "Properties" angesehen und muss
sagen: stimmt...
die machen da noch etwas mehr als nur nach "=" zu suchen, z.B. werden alle
"\uxxxx" in Unicode kodiert und die "\t", "\n" .. in die passenden
Sonderzeichen. Deswegen wahrscheinlich auch die Beschränkung auf "ISO
8859-1". Steht ja auch so in der doku zu "Properties"...

Also kann man "Properties" nicht aus einem String/StringBuffer befüllen,
ausser man nimmt einen "ByteArrayInputStream" und wandelt "String" nach
"byte[]" mit "String.getBytes("8859_1").

Vielleicht etwas umständlich, aber zumindest möglich...

Gruss
Joachim
Lothar Kimmeringer
2003-10-14 19:35:09 UTC
Permalink
Post by Joachim Karrer
Also kann man "Properties" nicht aus einem String/StringBuffer befüllen,
ausser man nimmt einen "ByteArrayInputStream" und wandelt "String" nach
"byte[]" mit "String.getBytes("8859_1").
Mit vielen Fragezeichen statt der Zeichen, die mal Unicode
und !8859_1 waren...


Gruesse, Lothar
--
Lothar Kimmeringer E-Mail: ***@kimmeringer.de
PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)

Always remember: The answer is forty-two, there can only be wrong
questions!
Patrick Roemer
2003-10-14 11:18:21 UTC
Permalink
Hallo,
Post by Joachim Karrer
Post by Patrick Roemer
| When saving properties to a stream or loading them from a stream, the
| ISO 8859-1 character encoding is used. For characters that cannot be
| directly represented in this encoding, Unicode escapes are used; [...]
(Properties API-Doc)
| "[...]however, only a single 'u' character is allowed in an escape
| sequence. The native2ascii tool can be used to convert property files to
| and from other character encodings."
Aua... das schreit nach "deprecation" (sprich, diese Klasse gehört
deprecated) und nach Einführen einer Properties-Klasse, welche mit dem
(neueren/anderen) Konzept der Reader/Writer arbeitet.
Das 'Format' ist wirklich nicht schoen, aber ich sehe nicht, wo
Reader/Writer da was verbessern koennten. Im Gegenteil.

Welcher Zeichensatz sollte denn dann verwendet werden? UTF-8? Oder gar
der 'Defaultzeichensatz', womit Properties-Dateien nicht mehr portabel
waeren? Und wie erzwingt man, dass der Nutzer auch wirklich einen
Reader/Writer, der auf diesen Zeichensatz geeicht ist, uebergibt?

Viele Gruesse,
Patrick
Joachim Karrer
2003-10-14 11:51:26 UTC
Permalink
Post by Patrick Roemer
Das 'Format' ist wirklich nicht schoen, aber ich sehe nicht, wo
Reader/Writer da was verbessern koennten. Im Gegenteil.
Welcher Zeichensatz sollte denn dann verwendet werden? UTF-8? Oder gar
der 'Defaultzeichensatz', womit Properties-Dateien nicht mehr portabel
waeren? Und wie erzwingt man, dass der Nutzer auch wirklich einen
Reader/Writer, der auf diesen Zeichensatz geeicht ist, uebergibt?
Ich seh's ein...
ist wirklich ein Grauss diese encodiererei... war's schon immer (ich sag nur
Codetables *grrrr*) und wird selbst jetzt mit Unicode nicht wirklich
besser.

Gruss
Joachim
Paul Ebermann
2003-10-13 23:23:42 UTC
Permalink
Post by Joachim Karrer
Post by Sven Köhler
Post by Manfred Pruntsch
In PHP gibt eine Möglichkeit assoziative Arrays ungefähr so zu
fooArray = {"key1"=>"a", "key2"=>"b"};
PHP ist eine Scriptsprache.
Du vergleichst hier Äpfel mit Birnen.
Aber schön wär's manchmal doch... (auch wenn man's nicht wirklich braucht
bzw. die Zuweisungen "selbstprogrammiert" effizienter gestalten kann.)
In PHP sind Arrays und Maps einfach das gleiche :-)
Post by Joachim Karrer
Ich hoffe bloss, dass hier in nächster Zeit keiner auf die Idee kommt und
fragt, warum 'foo["superHash"]="gehtnicht"' nicht von Java unterstützt
wird...
In C# geht das übrigens für Hashmaps (oder wie
auch immer die dort heißen) - es ist sogar die
einzige Möglichkeit, darauf zuzugreifen.


Paul, vor etwa 2 Jahren mal java.util.Hashtable
als Wrapper um die entsprechende Struktur
in C# nachprogrammiert habend ...
Armin Reichert
2003-10-14 19:26:39 UTC
Permalink
Post by Manfred Pruntsch
Hi,
String[] fooString = new String[]{"a", "b"};
HashMap fooHashMap = new HashMap(){"key1","a"; "key2","b"};
Hallo,

wie wäre es damit:

Map map = new HashMap();
{
map.put("key1", "value1");
// etc
}

oder

Map map = new HashMap()
{{
map.put("key1","value1");
// etc
}};

Die 2. Variante ist aber etwas abgefahren.

Gruß Armin
Stefan Matthias Aust
2003-10-14 22:25:17 UTC
Permalink
Post by Armin Reichert
Die 2. Variante ist aber etwas abgefahren.
...und erzeugt eine anonyme Klasse das in diesem Fall unnötig die
Anwendung vergrößert. Zudem müsste entweder map final sein oder aber es
reicht einfach this.put() bzw. put() zu benutzen.

bye
--
Stefan Matthias Aust // "Ist es normal, nur weil alle es tun?" -F4
Armin Reichert
2003-10-14 23:45:09 UTC
Permalink
Post by Stefan Matthias Aust
Post by Armin Reichert
Die 2. Variante ist aber etwas abgefahren.
...und erzeugt eine anonyme Klasse das in diesem Fall unnötig die
Anwendung vergrößert. Zudem müsste entweder map final sein oder aber es
reicht einfach this.put() bzw. put() zu benutzen.
Ok, hab' ich auf die schnelle falsch hingeschrieben, da sollte nur put(key,
value) stehen.

Variante 2 hat zwar eine nette Syntax, aber die von Stefan korrekt
beschriebenen Nachteile.

Gruß Armin

Loading...