Компаратор Java для байтового массива (лексикографический) - PullRequest
13 голосов
/ 24 февраля 2011

У меня есть хэш-карта с байтовыми ключами [].Я бы хотел отсортировать его с помощью TreeMap.

Какой самый эффективный способ реализации компаратора для лексикографического порядка?

Ответы [ 4 ]

22 голосов
/ 24 февраля 2011

Используя Гуава , вы можете использовать:

Компаратор UnsignedBytes имеет оптимизированную форму с использованием Unsafe, которую он использует, если может.Комментарии в коде указывают, что он может быть как минимум вдвое быстрее обычной реализации Java.

17 голосов
/ 24 февраля 2011

Нашел этот хороший кусок кода в Apache Hbase:

    public int compare(byte[] left, byte[] right) {
        for (int i = 0, j = 0; i < left.length && j < right.length; i++, j++) {
            int a = (left[i] & 0xff);
            int b = (right[j] & 0xff);
            if (a != b) {
                return a - b;
            }
        }
        return left.length - right.length;
    }
0 голосов
/ 24 февраля 2011

Я предполагаю, что проблема только в сравнении байтов и байтов. Работа с массивами проста, поэтому я не буду ее охватывать. Что касается байта против байта, моя первая мысль сделать это:

public class ByteComparator implements Comparator<byte> {
  public int compare(byte b1, byte b2) {
    return new Byte(b1).compareTo(b2);
  }
}

Но это не будет лексикографическим: 0xFF (байт со знаком для -1) будет считаться меньшим, чем 0x00, когда лексикографически оно больше. Я думаю, что это должно сработать:

public class ByteComparator implements Comparator<byte> {
  public int compare(byte b1, byte b2) {
    // convert to unsigned bytes (0 to 255) before comparing them.
    int i1 = b1 < 0 ? 256 + b1 : b1;
    int i2 = b2 < 0 ? 256 + b2 : b2;
    return i2 - i1;
  }
}

Возможно, что-то есть в библиотеках Apache commons-lang или commons-math, которые делают это, но я не знаю, как это делается.

0 голосов
/ 24 февраля 2011

Вы можете использовать компаратор, который объединяет Character.toLowerCase () каждого байта в массиве (при условии, что byte [] находится в ASCII), если нет, вам нужно будет самостоятельно выполнить декодирование символа или использовать new String(bytes, charSet).toLowerCase() но это вряд ли будет эффективным.

...