Как сгруппировать массив байт по количеству дубликатов?
Например есть массив байт:
116, 101, 116, 104, 101, 116
Нужно отсортировать так чтобы получился массив:
116,101,104
ну или хотя бы:
116,116,116,101,101,104
Ответы (4 шт):
Автор решения: ЮрийСПб
→ Ссылка
- Преобразуйте массив в List
- List-ом инициализируйте LinkedHashSet
- Создайте массив из LinkedHashSet
Автор решения: tym32167
→ Ссылка
Решение подразумевает, что порядок чисел в результате будет таким же, как в оригинальном массиве.
Если на входе у вас коллекция байт (то есть значение байта ограничено 0..255), то можно воспользоваться подсчетом, чтобы все операции заняли линейное время.
Пример
byte[] bytes = new byte[]{116, 101, 116, 104, 101, 116};
int[] counter = new int[256];
for (int i = 0; i < bytes.length; i++)
counter[bytes[i]]++;
byte[] result = new byte[bytes.length];
int pointerNew = 0;
int pointerOld = 0;
while (pointerOld < bytes.length) {
int count = counter[bytes[pointerOld]];
if (count > 0) {
for (int i = 0; i < count; i++) {
result[pointerNew] = bytes[pointerOld];
pointerNew++;
}
counter[bytes[pointerOld]] = 0;
}
pointerOld++;
}
System.out.println(Arrays.toString(result));
На выходе получаем
[116, 116, 116, 101, 101, 104]
Если вам на выходе нужны только уникальные значения, можно всего то поменять пару строк
byte[] bytes = new byte[]{116, 101, 116, 104, 101, 116};
int[] counter = new int[256];
int uniqueCount = 0;
for (int i = 0; i < bytes.length; i++) {
if (counter[bytes[i]] == 0) uniqueCount++;
counter[bytes[i]]++;
}
byte[] result = new byte[uniqueCount];
int pointerNew = 0;
int pointerOld = 0;
while (pointerOld < bytes.length) {
int count = counter[bytes[pointerOld]];
if (count > 0) {
result[pointerNew] = bytes[pointerOld];
counter[bytes[pointerOld]] = 0;
pointerNew++;
}
pointerOld++;
}
System.out.println(Arrays.toString(result));
На выходе получим
[116, 101, 104]
Автор решения: Олексій Моренець
→ Ссылка
List<Integer> integerStream = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet().stream()
.sorted((o1, o2) -> (int) (o2.getValue() - o1.getValue()))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
Output:
[116, 101, 104]
Автор решения: BccHnw
→ Ссылка
Можно и с BitSet поиграться (но не забывая, что byte со знаком). Если не пользоваться растущим списком, а сразу создавать массив, то два прохода. Первый подсчитывает, второй генерирует:
public class Main {
public static void main(String[] args) {
byte[] arr = { 116, 101, 116, 104, 101, 116, -7 };
BitSet bitSet = new BitSet();
for (byte rawByte : arr) {
int value = rawByte & 0xff;
bitSet.set(value);
}
byte[] result = new byte[bitSet.cardinality()];
int index = 0;
for (byte rawByte: arr) {
int value = rawByte & 0xff;
if (bitSet.get(value)) {
result[index++] = rawByte;
bitSet.clear(value);
}
}
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.toString(result));
}
}