#java
Вопрос:
У меня есть Listlt;Object[]gt; events
место, где [0]
в каждой строке указан идентификатор, который мне нужен. Также у меня int startSeq
есть определенный начальный номер.
Мне нужно получить Maplt;Integer,Integergt;
идентификатор события where -gt; startSeq igt; , где i-приращение на 1 от startSeq
.
Пример:
int startSeq = 6; Listlt;Object[]gt; events = dao.getEvents(); // ((Object[])events.get(0))[0] = 200676, ((Object[])events.get(1))[0] = 204561, ... 200676 -gt; 6 204561 -gt; 7 205156 -gt; 8
Проблема: Если я использую IntStream
опцию в качестве основы для своего потока, у меня нет способа отслеживать индекс списка (ключа) в toMap
:
Maplt;Integer,Integergt; map = IntStream.range(startSeq, startSeq events.size()) .boxed().collect(Collectors.toMap( x -gt; /* Can't track List, no relation to IntStream*/ Function.identity()))
Если я использую опцию потока списка в качестве основы, я не смогу отслеживать последовательное увеличение значения toMap
:
Maplt;Integer,Integergt; map = events.stream().collect(Collectors.toMap( x -gt; (Integer)x[0], y -gt; /* How to relate i increment from startSeq? */)
Ответ №1:
Вы можете выполнить итерацию по диапазону (startSeq, startSeq events.size()) и вычесть startSeq из каждого индекса, чтобы сопоставить элементы списка:
int startSeq = 6; Listlt;Object[]gt; events = List.of(new Object[]{200676,"foo"}, new Object[]{204561,"bar"}, new Object[]{205156,"baz"}); Maplt;Integer,Integergt; map = IntStream.range(startSeq, startSeq events.size()) .mapToObj(i -gt; Map.entry((Integer)(events.get(i-startSeq)[0]), i)) .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); System.out.println(map);
Если вам нужно, сохраняйте порядок вставки:
.... .collect(Collectors.toMap(Entry::getKey, Entry::getValue,(x, y) -gt; y, LinkedHashMap::new));
Ответ №2:
Одним из подходов было бы сделать следующее:
final int startSeq = 6; final Listlt;Object[]gt; events = List.of(new Object[] {1}, new Object[] {2}, new Object[] {3}); Maplt;Integer,Integergt; map = IntStream.range(0, events.size()) .boxed().collect(Collectors.toMap(i -gt; (Integer)events.get(i)[0], i -gt; startSeq i));
Пожалуйста, обратите внимание, что это может сработать только в том случае, если startSeq
и events
может быть сделано final
или member
изменено.
Ответ №3:
Воспользуйся AtomicInteger
:
AtomicInteger startSeq = new AtomicInteger(6); Maplt;Integer, Integergt; map = events .stream() .collect(Collectors.toMap( x -gt; (Integer)x[0], x -gt; startSeq.getAndIncrement() ));
или int[]
int[] startSeq = {6}; Maplt;Integer, Integergt; map = events .stream() .collect(Collectors.toMap( x -gt; (Integer)x[0], x -gt; startSeq[0] ));
Комментарии:
1. Могу ли я сделать это без
int[]
массива, точно так жеstartSeq
?2. Не используйте операции с отслеживанием состояния в потоках.
3. @gene.b, нет, как объяснялось ранее
startSeq
, должно быть фактически окончательным
Ответ №4:
Ты мог бы сделать это вот так. Возможно, вам придется немного изменить способ разыменования объекта события, о котором вы упомянули.
- потоковая передача индексов для размера массива
- сопоставьте значение и индекс с массивом
- затем соберите значения из массива и поместите их на карту.
int startSeq = 6; Maplt;Integer, Integergt; map = IntStream.range(0, events.size()) .mapToObj(i -gt; new int[] { (int)events.get(i)[0], i startSeq }) .collect(Collectors.toMap(arr -gt; arr[0], arr -gt; arr[1]));