我正试图找到一种方法来删除重复条目从字节数组'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;
}
我最大的遗憾是我如何重建'byte[][]'的返回值。我很确定有更好的办法,但我想不出来。我也瞄准JRE1.8。
假设您对CRC不产生假阳性有信心,或者您对消除此类假阳性的后果感到满意,那么做同样事情的另一种方法是使用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(n)而不是当前的O(n2)。
如果不希望出现误报,则需要围绕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>
来消除重复,同时保持相对顺序,并且没有消除误报的风险。
private byte[][] filterByteArrayValues(final byte[][] values) {
final Set<Byte[]> set = new HashSet<Byte[]>();
for (final byte[] value : values) {
set.add(value);
}
return set.toArray();
}
以下是您的一些优化方法:
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似乎是更好的主意。