Решал задачу через стримы и мапы.
Решение в итоге прошло и все ок, но я думаю что можно сделать как то проще, у меня сделано через три стрима. Код прикреплять нельзя, потому я прикреплю немного ломанный код который не работает.
// получаю мапу из коллекции байт которую я получил ранее и сразу суммирую количество вхождений
Map<Integer, Integer> frequency = bytes
.stream()
.collect(Collectors.toMap());
// получаю ключ значение с максимальными повторениями
Map.Entry<Integer, Integer> maxEntry = frequency.entrySet().stream()
.max(comparingByValue());
// сопоставляю в потоке значения ключей в отсортированном массиве (можно и не сортировать :) )
frequency
.entrySet()
.stream()
.sorted(comparingByValue().reversed())
.filter(e -> e.getValue() == maxEntry.getValue())
.forEach(k -> System.out.print(k.getKey() + " "));
// вопрос в следующем, я пытался реализовать такую логику в одном потоке, то есть
1. получаю мапу из массива байтов (тут получаю "ключ" : "количество вхождений ключа в коллекции")
2. Сортирую мапу по количеству вхождений ключей (тут получаю допустим { 90 - 4 ; 80 - 2 ; 12 - 1; 10 -1 }
дальше я предполагаю получить максимальное значение (то есть 4) и сразу фильтровать поток как представлено в коде и отсекать пары у которых значения не равны максимальному (то есть 4)
Как сделать проще ? (или как завернуть все в один поток)
подскажите плез, четыре часа сижу уже)
Aleksey
41 уровень
Stream-ы
Решен
Комментарии (16)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
ГоффMaster
17 декабря 2022, 15:18
Так вопрос то в чём - можно ли проще или делал кто также, через стримы?
0
AlekseyРаботает в DжаваРаш
17 декабря 2022, 15:24
Как сделать проще
0
AlekseyРаботает в DжаваРаш
17 декабря 2022, 15:26
исправил вопрос
0
ГоффMaster
17 декабря 2022, 16:01
Если я правильно помню задачу, то там надо из файла зачитать байты и вывести наиболее встречающийся байт, так?
Самое простое решение, которое тут встречалось - это через массив int[256]. При этом индекс массива - это, собственно, сам байт, а значение в массиве - это сколько раз этот байт встречается. Помним, что байт - это 0 до 255? Поэтому int[256]
Выглядит вот так:
+1
AlekseyРаботает в DжаваРаш
17 декабря 2022, 19:19
не, там надо вывести байтовое значение массива которое повторяется больше всех раз
и если их несколько то надо вывести все значения через пробел
0
ГоффMaster
17 декабря 2022, 19:25
Не понял, что такое "байтовое значение массива" и посмотрел задачу.
"Ввести с консоли имя файла. Найти байт или байты с максимальным количеством повторов. Вывести их на экран через пробел. Закрыть поток ввода-вывода."
Самое оптимальное из всех тут виданных решений этой задачи я и привёл, если что непонятно - спрашивай.
0
AlekseyРаботает в DжаваРаш
17 декабря 2022, 21:07
в твоем решении все понятно, мой первоначальный вопрос был не в этом.
Эту задачу я решил, и думаю, что можно сделать проще через стримы. (об этом как раз мой вопрос)
0
AlekseyРаботает в DжаваРаш
17 декабря 2022, 21:18
решение действительно простое. Мне нравится)
0
ГоффMaster
17 декабря 2022, 21:52
Когда мы говорим о том, что решение проще, то всегда надо задавать вопрос - а для кого проще? Для прогера, потому что строк кода писать меньше или для машины проще, потому что меньше считать? Я бы интересы машины ставил над желаниями программиста, ибо прогер написал программу и ушёл к другой, а машине с этим кодом ещё долгое время возиться, выполнять сотни/тысячи/миллионы раз.
Скорее всего, для машины решение через стримы будет в разы труднее. Я не знаю, как стримы и мапы реализованы, но в любом случае это явно значительно более сложные и ресурсозатратные штуки, чем простой массив.
Но в рамках учебы оно конечно можно и даже нужно решать по-всякому ;-)
0
DanielCEO в BicycleInventionAcad
18 декабря 2022, 04:36
Как написали выше, решение через int[256] самое простое, но оно применимо только для конкретной задачи (и еще большой вопрос, что будет эффективнее, если у нас будет не 256, а, скажем, пару миллионов возможных значений). Поэтому вот мое решение без стримо (можно было и через стримы, но как-то не улыбалась мне тогда перспектива мучиться с двойным дженериком там).
Читаем файл в байтовый буффер. Итерируем по ключу. Если ключ есть, увеличиваем значение в мапе на 1. Если ключа нет, добавляем пару (ключ, 1). А потом проходимся еще раз по всей мапе и сравниваем элементы по кол-ву вхождений. Если оно превышает текущее максимальное, то затираем лист и добавлям новый максимум. Если равно максимальному, то просто добавляем в лист. Если меньше максимума, то игнорируем. А дальше просто вывод листа.
0
ГоффMaster
18 декабря 2022, 14:09
Да, можно и так, я сам сделал и с массивом, и с мапой. С мапой сделал два раза - если мне памятка не изменяет, с методом putIfAbsent() и ещё с методом getOrDefault(). Посмотри на них, они вот прямо для таких случаев.
ПыСы: В те времена, когда в байт будет влезать пара миллионов возможных значений, джава будет уже не актуальна ;-)
0
DanielCEO в BicycleInventionAcad
18 декабря 2022, 15:24
Методы интересные. Особенно первый, потому что его, по факту и реализовывал вручную.
На самом деле очень плохо знаком с Collection framework, потому что не дошел до него еще. Завяз на регулярках и паттернах. Так что мапа это прям темный лес. Когда придет время, сунемся и туда)
Дай бог дожить до этого светлого момента)
А вообще я имел в виду ситуацию, когда нам нужно посчитать количество вхождений каких-то более объемных объектов. К примеру у нас есть список интов, которые нужно точно так же проверить. Один только массив будет занимать 16 гигов памяти. Не очень то эффективно получается. А если нам нужно сделать то же самое со словами? Их в принципе с индексом массива никак не свяжешь. Поэтому повторюсь: локально это оптимальное решение, но работает оно только локально)
0
ГоффMaster
18 декабря 2022, 16:53
Я с тобой согласен на все 100 процентов ;-) Но всё равно немного поворчу :-)
Скалируемость важна, но не качественная, а количественная. Алгоритм должен уверенно работать при изменении количества, но не типа исходных данных. Изменение типа исходных данных - это всегда новое задача, требующая нового решения. Невозможно придумать программу, решающую любой вопрос, мы просто получим на выходе 42, если эта цифра о чём-то говорит. Если нет - погугли про неё.
Будет список интов - будем думать, как его окучить. Если список будет большой - будем думать, как большой список окучить, разбив его на кусочки. Будут слова - ну будем думать, как со словами быть, там вообще может через кастомные хеши будет оптимальнее всего. И помним при этом, что с точки зрения памяти, массив более лучше чем любая мапа.
Но в чём согласен на все 100 - учится надо всему, и мапы, и методы, и вот те же регулярки! Поэтому задачи решать разными способами, особенно те, которые вот такие интересные при кажущейся простоте, как эта.
0
DanielCEO в BicycleInventionAcad
19 декабря 2022, 07:18
Грешно не читать не такие книжки. Так что да, полное 42)
Регулярки это жесть. Язык внутри языка. В итоге пообщался со знакомыми, получил ответ, что дай бог пару раз в год сталкиваются с этим и решил остановиться на уровне знаний "могу запарсить что-нибудь простенькое". Здесь регулярно пригождается.
Сейчас куда интереснее поттерны разбирать. Потому что первый опыт построение собственной программы показал, что без нормальной продуманной структуры код рассыпается еще до того как начнет работать, не говоря уже о расширении.
Но пока это выглядит как в том анекдоте: "Вот так, с помощью нехитрых приспособлений буханку белого (или черного) хлеба можно превратить в троллейбус. Но зачем?.."
+1
AlekseyРаботает в DжаваРаш
20 декабря 2022, 01:28
Мое первое решение.
Написал код как подсказали с простым массивом и протестировал на файле в 250кб с замером времени.
Результат практически одинаковый, оба решения показывают в районе +-500 мс) (это насчет труднозатратности для машины)
И там и там не учитывал время на создание потоков - чисто работа программы)
0
DanielCEO в BicycleInventionAcad
20 декабря 2022, 11:56
Попробуйте обернуть FileInputStream в BufferedInputStream по аналогии с ридером. Должно ускорить работу, так как в этом варианте чтение из файла происходит побайтово, а обращение к файловой системе это очень затратный процесс. Лучше один раз обратиться, считать все в буфер, а потом уже с ним работать.
0