In So verwenden Sie ein Array für den Schlüssel von HashMap sollte es anders sein, wenn es TreeMap ist, aber ich konnte es nicht sofort überprüfen, also habe ich es geteilt.
Hier heißt es TreeMap. HashMap ist etwas anders. → Verwendung eines Arrays für HashMap-Schlüssel Die Hauptannahme ist --Implementieren gleich --Comparator wird an oder TreeMap übergeben, das Comparable implementiert
Das erste ist, dass das enthältKey, get und put von TreeSet compareTo verwendet. Genau genommen ist dies möglicherweise nicht erforderlich, aber es ist erforderlich. Das zweite ist, dass die Implementierung von Compareable die Implementierung von compareTo bedeutet. Wenn es nicht vergleichbar gemacht werden kann, bereiten Sie einen separaten Komparator vor und übergeben Sie ihn an den TreeMap-Konstruktor. Der dritte ist nicht unveränderlich und kann später geändert werden. Wenn Sie jedoch den Schlüsselwert nach dem Einfügen ändern, wird er möglicherweise nicht gefunden. Dies ist in einem gegabelten Baum implementiert. Wenn Sie also den Schlüssel von außen ändern und rechts oder links falsch sind, explodiert er.
Der Unterschied zwischen HashMap und TreeMap besteht darin, ob Sie hashCode oder compareTo benötigen. Wenn Sie beide haben, können Sie sowohl HashMap als auch TreeMap verwenden.
Wenn es sich um ein Array handelt, ist equals nicht korrekt und implementiert Comparable nicht.
Main.java
public static void main(String[] args) {
byte[] b01 = { 1, 2, 3 };
byte[] b02 = { 1, 2, 3 };
System.out.println(b01 == b02);
System.out.println(b01.equals(b02));
System.out.println(Arrays.equals(b01, b02));
//Comparable c = (Comparable)b01;
TreeMap<byte[], String> map = new TreeMap<>();
map.put(b01, "OK");
}
Auskommentierte Casts führen zu einem Kompilierungsfehler. Wenn du rennst ...
false
false
true
Exception in thread "main"
java.lang.ClassCastException: [B cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1290)
at java.util.TreeMap.put(TreeMap.java:538)
at Main.main(Main.java:15)
Ich habe Arrays.equals, aber ich muss mich selbst vergleichen.
Ich habe mich gefragt, wer Comparable überhaupt implementiert hat, und als ich grep habe, habe ich auch das java.nio.Buffer-Corps implementiert.
Lass es uns testen.
Main.java
public static void main(String[] args) {
byte[] b01 = { 1, 2, 3 };
byte[] b02 = { 1, 2, 3 };
ByteBuffer w01 = ByteBuffer.wrap(b01);
ByteBuffer w02 = ByteBuffer.wrap(b02);
Map<ByteBuffer, String> map = new TreeMap<>();
map.put(w01, "OK");
System.out.println(w01 == w02);
System.out.println(w01.equals(w02));
System.out.println(map.get(w01));
System.out.println(map.get(w02));
}
Wenn du rennst ...
false
true
OK
OK
OK überhaupt. Das ist das beste Gefühl. Ich mag die Standardbibliothek, die aus JDK 1.4 hinzugefügt wurde.
Ich wage es, eine Klasse zu erstellen, die Byte [] umschließt. Ich habe ByteBuffer als Referenz verwendet.
ByteArrayWrapper.java
import java.util.Arrays;
public class ByteArrayWrapper implements Comparable<ByteArrayWrapper> {
private byte[] data;
public ByteArrayWrapper(byte[] data) {
this.data = data.clone();
}
public boolean equals(Object other) {
if (other instanceof ByteArrayWrapper) {
return Arrays.equals(data, ((ByteArrayWrapper) other).data);
}
return false;
}
public int compareTo(ByteArrayWrapper that) {
int n = Math.min(this.data.length, that.data.length);
for (int i = 0; i < n; i++) {
int cmp = Byte.compare(this.data[i], that.data[i]);
if (cmp != 0)
return cmp;
}
return this.data.length - that.data.length;
}
}
Lass es uns testen.
Main.java
public static void main(String[] args) {
byte[] b01 = { 1, 2, 3 };
byte[] b02 = { 1, 2, 3 };
ByteArrayWrapper w01 = new ByteArrayWrapper(b01);
ByteArrayWrapper w02 = new ByteArrayWrapper(b02);
Map<ByteArrayWrapper, String> map = new TreeMap<>();
map.put(w01, "OK");
System.out.println(w01 == w02);
System.out.println(w01.equals(w02));
System.out.println(map.get(w01));
System.out.println(map.get(w02));
}
Ergebnis ist ···
false
true
OK
OK
Ich klone () dieses Mal basierend auf der Lektion, die ich von HashMap gelernt habe, aber es ist wahrscheinlich in Ordnung.
(1/18 postscript) Ich habe versucht, das Problem zu beheben, indem ich das Argument des Konstruktors im Kommentar von byte [] in byte ... (Argument variabler Länge) geändert habe.
ByteArrayWrapper.java
import java.util.Arrays;
public class ByteArrayWrapper implements Comparable<ByteArrayWrapper> {
private byte[] data;
public ByteArrayWrapper(byte... data) {
this.data = data.clone();
}
public boolean equals(Object other) {
if (other instanceof ByteArrayWrapper) {
return Arrays.equals(data, ((ByteArrayWrapper) other).data);
}
return false;
}
public int compareTo(ByteArrayWrapper that) {
int n = Math.min(this.data.length, that.data.length);
for (int i = 0; i < n; i++) {
int cmp = Byte.compare(this.data[i], that.data[i]);
if (cmp != 0)
return cmp;
}
return this.data.length - that.data.length;
}
}
Sie können das Array wie zuvor oder als ByteArrayWrapper (1, 2, 3) übergeben. Es sollte sein, aber es gab nicht viel Verdienst im Bytetyp, weil es Casting erforderte. Mit int type und long type können Sie eine Instanz ohne Casting und ohne Vorbereitung eines Arrays erstellen.
Main.java
public static void main(String[] args) {
byte[] b01 = { 1, 2, 3 };
ByteArrayWrapper w01 = new ByteArrayWrapper(b01);
ByteArrayWrapper w02 = new ByteArrayWrapper((byte)1, (byte)2, (byte)3);
Map<ByteArrayWrapper, String> map1 = new HashMap<>();
map1.put(w01, "OK");
Map<ByteArrayWrapper, String> map2 = new TreeMap<>();
map2.put(w01, "OK");
System.out.println(map1.get(w01));
System.out.println(map1.get(w02));
System.out.println(map2.get(w01));
System.out.println(map2.get(w02));
}
java.math.BigInteger ist ebenfalls vergleichbar, kann jedoch nicht verwendet werden, da aus {0, 100} {100} wird.
Es wäre schön, wenn HashMap eindeutig wäre, aber TreeMap hat eine Größenbeziehung, sodass es keine andere Wahl gibt, als den numerischen Wert auf eine feste Länge festzulegen. Wenn nicht genügend Ziffern vorhanden sind, geben Sie links 0 ein.
(1/18 Nachschrift) Am Anfang schrieb ich, dass "Comparable implementiert ist oder Comparer an TreeMap übergibt", und ich machte nur das Beispiel von Comparable, also machte ich zusätzlich ein Beispiel von Comparer.
Teil 1 bis Teil 3 ist eine Methode zum Implementieren und Realisieren von Comparable, die Byte [] umschließt. Der fünfte ist der Fall der Herstellung eines Komparators, der eine andere Methode darstellt.
Es ist fast dasselbe wie compareTo von ByteArrayWrapper, erstellt jedoch ByteArrayComparator.
ByteArrayComparator.java
import java.util.Comparator;
public class ByteArrayComparator implements Comparator<byte[]> {
public int compare(byte[] o1, byte[] o2) {
int n = Math.min(o1.length, o2.length);
for (int i = 0; i < n; i++) {
int cmp = Byte.compare(o1[i], o2[i]);
if (cmp != 0)
return cmp;
}
return o1.length - o2.length;
}
}
Lass es uns testen.
Main.java
public static void main(String[] args) {
byte[] b01 = { 1, 2, 3 };
byte[] b02 = { 1, 2, 3 };
Map<byte[], String> map = new TreeMap<>(new ByteArrayComparator());
map.put(b01, "OK");
System.out.println(map.get(b01));
System.out.println(map.get(b02));
}
Ergebnis ist ···
OK
OK
Vielleicht ist es okay.
Es wurde bestätigt, dass ByteArrayWrapper keinen HashCode in TreeMap benötigt, aber normalerweise ist es besser, beide zu implementieren, wenn Sie es trotzdem machen. (1/18 postscript) Ich habe das Argument des Konstruktors von byte [] in byte ... geändert (Argument variabler Länge). Auch hinzugefügt gleich (Byte [] andere).
ByteArrayWrapper.java
import java.util.Arrays;
public class ByteArrayWrapper implements Comparable<ByteArrayWrapper> {
private byte[] data;
public ByteArrayWrapper(byte... data) {
this.data = data.clone();
}
public boolean equals(Object other) {
if (other instanceof ByteArrayWrapper) {
return equals(((ByteArrayWrapper) other).data);
}
return false;
}
public boolean equals(byte[] other) {
return Arrays.equals(data, other);
}
public int hashCode() {
return Arrays.hashCode(data);
}
public int compareTo(ByteArrayWrapper that) {
int n = Math.min(this.data.length, that.data.length);
for (int i = 0; i < n; i++) {
int cmp = Byte.compare(this.data[i], that.data[i]);
if (cmp != 0)
return cmp;
}
return this.data.length - that.data.length;
}
}
Main.java
public static void main(String[] args) {
byte[] b01 = { 1, 2, 3 };
ByteArrayWrapper w01 = new ByteArrayWrapper(b01);
ByteArrayWrapper w02 = new ByteArrayWrapper((byte)1, (byte)2, (byte)3);
Map<ByteArrayWrapper, String> map1 = new HashMap<>();
map1.put(w01, "OK");
Map<ByteArrayWrapper, String> map2 = new TreeMap<>();
map2.put(w01, "OK");
System.out.println(map1.get(w01));
System.out.println(map1.get(w02));
System.out.println(map2.get(w01));
System.out.println(map2.get(w02));
}
Wenn ich teste ...
OK
OK
OK
OK
Recommended Posts