Други, а кто понимает в Java? (Особую надежду возлагаю на
k_79.) Расскажите мне понятными словами, как бы мне сделать хэш, который бы в качестве ключа использовал 64-битное число, значение выдавал 48-битное (а лучше сразу byte[6]), а ещё был фиксированного размера и при превышении оного старые записи удалял? Про LinkedHashMap я читал, но ничего толком не понял. Там объекты какие-то толпами, а у меня просто числа...
Я вот пробовал породить класс, который extends LinkedHashMap<Long, byte[6]>,
и метод removeEldestEntry или как его там переопределил правильно. Из своего 64-битного числа я генерю Long, а в свои массивы запиываю то, что даёт get(мойключ), и если дал null, то тогда массив руками считаю и в хэш запихиваю посредством put(мойключ, посчитанныймассив). И ничего не получается — какие-то бредовые результаты, совсем всё не так, как если бы каждый раз руками массив считать.
Что делать-то, а? Только я Java не знаю, и программировать на ней не умею.
Я вот пробовал породить класс, который extends LinkedHashMap<Long, byte[6]>,
и метод removeEldestEntry или как его там переопределил правильно. Из своего 64-битного числа я генерю Long, а в свои массивы запиываю то, что даёт get(мойключ), и если дал null, то тогда массив руками считаю и в хэш запихиваю посредством put(мойключ, посчитанныймассив). И ничего не получается — какие-то бредовые результаты, совсем всё не так, как если бы каждый раз руками массив считать.
Что делать-то, а? Только я Java не знаю, и программировать на ней не умею.
no subject
2. Наеюсь, что 1 - нет, тогда нужен список операций - типа get, put, remove, get/setLimit, getSize, whatever.
no subject
no subject
ЗЫ: На Джаве я уж года три как ничего не программал, так что ни разу уже не эксперт.
no subject
no subject
no subject
no subject
no subject
no subject
no subject
public static void main(String[] args) { if (new byte[] {0, 1, 2, 3}.equals(new byte[] {0, 1, 2, 3})) System.out.println("same"); else System.out.println("different"); }Выводит, очевидно, different.
no subject
public static void main(String[] args) { System.out.println(new byte[] {0, 1, 2, 3}.hashCode()); System.out.println(new byte[] {0, 1, 2, 3}.hashCode()); }выводит разные значения.
no subject
Я сейчас дотестирую классик и вышлю.
no subject
package spb.dev2dev.avysk; import java.util.Map; import java.util.LinkedHashMap; import java.util.Arrays; /** * @author alf */ public class LongMap { private static int SIZE_LIMIT = 50; private Map storage = new LinkedHashMap() { protected boolean removeEldestEntry(Map.Entry eldest) { return size() > SIZE_LIMIT; } }; public byte[] get(byte[] key) { ByteBag bag = (ByteBag) storage.get(new ByteBag(key)); return bag == null ? null : bag.getValue(); } public byte[] remove(byte[] key) { ByteBag bag = (ByteBag) storage.remove(new ByteBag(key)); return bag == null ? null : bag.getValue(); } public byte[] put(byte[] key, byte[] value) { ByteBag oldBag = (ByteBag) storage.put(new ByteBag(key), new ByteBag(value)); return oldBag == null ? null : oldBag.getValue(); } // add size() and other methods if necessary private static class ByteBag { private byte[] value; public ByteBag(byte[] value) { this.value = value; } public byte[] getValue() { return value; } public boolean equals(Object obj) { ByteBag bb = (ByteBag) obj; return Arrays.equals(value, bb.getValue()); } public int hashCode() { return Arrays.hashCode(value); } } }no subject
1. Унаследоваться от класса
2. Сложить объект этого класса в поле и использовать его
В общем случае вариант 2 много, много лучше - он не создаёт неочевидных связей. Да, приходится писать кучу бессмысленных методов для прокидывания вызовов - но вероятность нарваться на чудеса в поведении минимальна.
no subject
no subject
Имя -> телефон и внитри для этой пары жава вычислит хэш
добавляют вот так
put(Object key, Object value) или
put( "Вася", "+35850123456" )
http://java.sun.com/j2se/1.3/docs/api/java/util/HashMap.html
тебе это надо? Если нет, то пользуйся HashSet
http://java.sun.com/j2se/1.3/docs/api/java/util/Set.html
используй для получения хэш кода
public int hashCode()
Returns the hash code value for this set.
http://java.sun.com/j2se/1.3/docs/api/java/util/AbstractSet.html#hashCode()
no subject
no subject
no subject
no subject
С лонгом будет быстрее, да... Наверное. Может быть :)
no subject
no subject
package spb.dev2dev.avysk; import java.util.LinkedHashMap; import java.util.Map; import java.util.Arrays; /** * @author alf */ public class LongMap { private static int SIZE_LIMIT = 4; public static void main(String[] args) { LongMap map = new LongMap(); map.put(new byte[] {1, 2, 3, 4, 5, 6, 7, 8,}, new byte[] {1, 2, 3, 4, 5, 6,}); map.put(new byte[] {2, 2, 3, 4, 5, 6, 7, 8,}, new byte[] {2, 2, 3, 4, 5, 6,}); map.put(new byte[] {3, 2, 3, 4, 5, 6, 7, 8,}, new byte[] {3, 2, 3, 4, 5, 6,}); map.put(new byte[] {4, 2, 3, 4, 5, 6, 7, 8,}, new byte[] {4, 2, 3, 4, 5, 6,}); map.put(new byte[] {5, 2, 3, 4, 5, 6, 7, 8,}, new byte[] {5, 2, 3, 4, 5, 6,}); print(map.get(new byte[] {1, 2, 3, 4, 5, 6, 7, 8,})); print(map.get(new byte[] {2, 2, 3, 4, 5, 6, 7, 8,})); print(map.get(new byte[] {3, 2, 3, 4, 5, 6, 7, 8,})); print(map.get(new byte[] {4, 2, 3, 4, 5, 6, 7, 8,})); print(map.get(new byte[] {5, 2, 3, 4, 5, 6, 7, 8,})); } private Map storage = new LinkedHashMap() { protected boolean removeEldestEntry(Map.Entry eldest) { return size() > SIZE_LIMIT; } }; public byte[] get(byte[] key) { return (byte[]) storage.get(toLong(key)); } public byte[] remove(byte[] key) { return (byte[]) storage.remove(toLong(key)); } public byte[] put(byte[] key, byte[] value) { return (byte[]) storage.put(toLong(key), value); } private static Long toLong(byte[] a) { long result = 0L; for (int i = 0; i < a.length; i++) { result <<= 8; result |= a[i]; } return Long.valueOf(result); } private static void print(byte[] a) { if (a==null) { System.out.println("null"); return; } for (int i = 0; i < a.length; i++) { System.out.print(a[i] + ", "); } System.out.println(); } }no subject
// Arrays.java, jdk1.5.0_07 public static int hashCode(byte a[]) { if (a == null) return 0; int result = 1; for (byte element : a) result = 31 * result + element; return result; }Для массивов хэшкод считается как для
Object- это (очень грубо) внутренный адрес объекта.Почему в Java так сделано - не знаю, потому и написал
ByteBag. А вот вариант cLongнадо погонять ещё - я знаю, чтоByteBagявляется "правильным" ключом, то есть мы точно не слепляем значения. А вот в методе toLong надо проверить, что он не теряет биты.Так что в обычной жизни я бы плюнул на производительность и остался с
ByteBag:)no subject
private static Long toLong(byte[] a) { long result = 0L; for (int i = a.length; --i >= 0;) { result <<= 8; result |= a[i]; } return Long.valueOf(result); }будет чуток быстрее, а порядок байтов тебе тут всё равно не важен.
no subject
map.put(new byte[] {-128, -128, 0, 0, 0, 0, 0, 0,}, new byte[] {0, 0, 0, 0, 0, 0,});
map.put(new byte[] {96, -128, 0, 0, 0, 0, 0, 0,}, new byte[] {32, 0, 0, 0, 0, 0,});
print(map.get(new byte[] {-128, -128, 0, 0, 0, 0, 0, 0,}));
Результат — 32, 0, 0, 0, 0, 0. :(
Что я делаю не так?
no subject
no subject
no subject
private static Long toLong(byte[] a) { long result = 0L; for (int i = 0; i < a.length; i++) { result <<= 8; result |= (0xffL & a[i]); } return Long.valueOf(result); }Дело в том, что
result |= a[i];эквивалентноresult = result | a[i];, а это значит, чтоa[i]будет приведено кlong. Посколькуbyteв Java signed, то -1 в конце массива угробит весь наш ключ.no subject
no subject
no subject
public static boolean equals(byte[] a, byte[] a2) { if (a == a2) return true; if (a == null || a2==null) return false; int length = a.length; if (a2.length != length) return false; for (int i = 0; i < length; i++) if (a[i] != a2[i]) return false; return true; }no subject
no subject
И привет Лаперье, ага.