2015-09-07 1 views
2

Я пытаюсь найти способ удалить повторяющиеся записи из байтового массива 'byte [] []', возвращенный как новый байт [] [] '. Код, как у меня сейчас, кажется, работает, но выглядит очень уродливо, и мне интересно, есть ли у кого-нибудь лучшие трюки, чтобы улучшить его. Функция я создал выглядит следующим образом:Есть ли более чистый способ уменьшить этот многомерный массив байтов, чтобы удалить дубликаты?

private byte[][] filterByteArrayValues(final byte[][] values) 
{ 
    final ArrayList<byte[]> listOfBytes = new ArrayList<byte[]>(); 
    final ArrayList<String> listOfCrc32 = new ArrayList<String>(); 
    for (final byte[] value : values) 
    { 
     final String crc = this.generateCheckSum(value); 
     if (!listOfCrc32.contains(crc)) 
     { 
      listOfCrc32.add(crc); 
      listOfBytes.add(value); 
     } 
    } 
    final byte[][] output = new byte[listOfBytes.size()][]; 
    for (int i = 0; i < listOfBytes.size(); i++) 
    { 
     output[i] = listOfBytes.get(i); 
    } 

    return output; 

} 

Мое самое большое сожаление, как я восстановление "байт [] [] для возвращаемого значения. Я почти уверен, что есть лучший способ, но я не могу думать об этом. Также я нацелен на JRE1.8.

+0

CRC может давать ложные срабатывания: списки разных байтов, которые производят одну и ту же контрольную сумму. – biziclop

+0

Хм .. не думал об этом. Я посмотрю на это спасибо @biziclop – JRSofty

ответ

4

Если предположить, что у вас есть уверенность в КПР не производить ложных срабатываний, или в порядке с последствиями устранения таких ложных срабатываний, еще один способ сделать то же самое будет с помощью HashMap:

private byte[][] filterByteArrayValues(final byte[][] values) { 
    final Map<String,byte[]> res = new HashMap<>(); 
    for (final byte[] value : values) { 
     res.put(generateCheckSum(value), value); 
    } 
    return res.values().toArray(new byte[res.size()][]); 
} 

Относительный порядок байтовых массивов может измениться, и вместо первого появления массива, созданного вашим кодом, вы получите последний.

Если вам не нравится переназначения, используйте метод, но заменить ArrayList<String> с HashSet<String>, чтобы сделать вашу фильтрацию в О (п) вместо текущего O (п).

Если вы не хотите ложных срабатываний, вам нужно построить некоторую инфраструктуру вокруг byte[] массива, чтобы сделать их пригодными для использования в хэш-контейнеров:

class Mva { // Multi-valued attribute 
    private final byte[] data; 
    public Mva(byte[] data) { this.data = data; } 
    @Override 
    public int hashCode() { 
     // return CRC similar to your generateCheckSum 
    } 
    @Override 
    public boolean equals(Object other) { 
     // Cast other to Mva, and compare individual values in data[] 
    } 
} 

Теперь вы можете использовать LinkedHashSet<Mva> для устранения дубликатов при сохранении относительный порядок и без риска устранения ложных срабатываний.

+0

Не уверен, могу ли я рискнуть переупорядочением байтов. Возвращаемое значение в конечном итоге входит в сервер каталогов. Эти байтовые массивы представляют собой несколько записей в атрибуте с несколькими значениями. – JRSofty

+0

Я дам вам попытку и дам вам знать, как это происходит, спасибо за идеи. Использование HashMap, хотя и немного удивительное вначале, похоже на гладкий способ решения проблемы. – JRSofty

+0

Да, это так. Спасибо за вашу помощь. – JRSofty

0
private byte[][] filterByteArrayValues(final byte[][] values) { 

    final Set<Byte[]> set = new HashSet<Byte[]>(); 

    for (final byte[] value : values) { 
     set.add(value); 
    } 

    return set.toArray(); 
} 
+0

Обратите внимание, как OP использует свой метод 'generateCheckSum' для сравнения массивов байтов. – dasblinkenlight

+0

Я (наивно), предполагая, что он использует 'generateCheckSum' как способ проверить равенство между' byte [] 's' – McNultyyy

+0

@McN да, это была идея, но, как кто-то прокомментировал мой первоначальный вопрос, который может привести к сбою поскольку CRC32 может генерировать ложные срабатывания. В любом случае я планирую сократить конечный результат, если в исходном (параметрическом) массиве массивов байтов есть дубликаты. – JRSofty

0

Вот ваш подход с некоторыми оптимизациями:

private byte[][] filterByteArrayValues(final byte[][] values) { 
    final Map<String, Integer> map = new HashMap<>(); 
    for (int i = 0; i < values.length; ++i) { 
     map.put(generateCheckSum(value), i); 
    } 
    Integer[] validInexes = map.values().toArray(new Integer[map.size()]); 
    byte[][] out = new byte[validInexes.length][]; 
    for (int i = 0; i < validInexes.length; ++i) { 
     out[i] = values[validInexes[i]]; 
    } 
    return out; 
} 

Но переопределить equals и hashCode и просто поставить каждое значение в HashSet кажется лучшей идеей.

Смежные вопросы