Как автоматически увеличить ключ hashmap, используя коллекторы и поток в Java 8
Я новичок в Java 8 потоков и коллекционеров.
Я читаю файл, содержимое которого нужно сохранить в connectedHashMap, где ключ - это номер строки файлов, а значения - его содержимое в этой строке.
Здесь я хочу использовать концепцию потока, но я не могу использовать Collectors.toMap для автоинкрементации ключей, которые необходимо сохранить в LinnkedHashMap, но я получаю исключения.
Ниже приведен код, который я пытаюсь
# List<String> list = new ArrayList<>();
Integer count=0;
try (BufferedReader br = Files.newBufferedReader( Paths.get( fileName ) )) {
// br returns as stream and convert it into a List
list = br.lines().collect( Collectors.toList() );
}
catch ( IOException e ) {
e.printStackTrace();
}
list.forEach( System.out::println );
Map<Integer, String> fileNumWithContentMapper = list.stream()
.collect( Collectors.toMap( n->n+1,s1->s1) );
#
2 ответа
Есть много способов это сделать. Но здесь я объясню свой путь:
1. Установите размер IntStream
объект.
Во-первых, всякий раз, когда у вас есть List<E>
объектов (т.е. E
может быть String
, Integers
, Objects
и т. д.) вы можете преобразовать его в Map<Integer, E>
используя IntStream
учебный класс. Этот класс представляет собой последовательность примитивных int-значимых элементов, которые поддерживают последовательные и параллельные агрегатные операции. Это значит как огромный счетчик. Если у нас уже есть счетчик, нам нужно установить некоторые ограничения и IntStream.range(int start, int end)
метод поможет нам. Этот метод возвращает последовательный порядок IntStream
от start
(включительно) до end
(эксклюзивно) с шагом 1. Таким образом, если вы хотите создать IntStream
с размером нашего List
использовать этот:
List<Integer> numbers = Arrays.asList(4, 5, 4, 3);
IntStream stream = IntStream.range(0, numbers.size);
2. Подготовить Stream
объект на основе IntStream
объект.
Теперь у нас есть счетчик размера вашего List<E>
, но нам нужен Map<Integer, E>
, Ну, теперь мы будем использовать IntStream.boxed()
, Этот метод возвращает Stream
состоящий из элементов этого потока, каждый в Integer
, Это Stream<Integer>
, Мы почти закончили.
Stream<Integer> streamBoxed = stream.boxed();
3. Конвертировать Stream
возражать против Map
объект
Наконец, мы можем создать карту, используя Stream.collect()
метод. Этот метод выполняет изменяемую операцию сокращения над элементами этого потока. Это сокращение будет сложным, если у нас не было помощи Collectors.toMap()
метод. Этот сборщик можно использовать для сбора элементов Stream в экземпляр Map. Для этого нам нужно предоставить две функции: keyMapper
а также valueMapper
, keyMapper
будет использоваться для извлечения Map
ключ от Stream
элемент и valueMapper
будет использоваться для извлечения <value>
связано с данным <key>
, Для нашего примера мы будем использовать Map<Integer, Integer>
, keyMapper
будут значения steamBoxed
поток мы можем извлечь, используя i -> i
и valueMapper
должны быть значения numbers
список получим, используя i -> numbers.get(i)
как это:
Map<Integer, Integer> result = streamBoxed.collect(Collectors.toMap(i -> i, i -> numbers.get(i)))
4. Объедините все шаги
Эти три части могут быть объединены в этот простой код:
List<Integer> numbers = Arrays.asList(4, 5, 4, 3);
Map<Integer, Integer> result = IntStream
.range(0, numbers.size); // IntStream
.boxed(); // Stream<Integer>
.collect(Collectors.toMap(i -> i, i -> numbers.get(i))) // Map<Integer, Integer>
Также вы обнаружите, что некоторые авторы предпочитают использовать Function.identity()
метод как keyMapper
, а также numbers::get
лямбда-выражение как valueMapper
, Почему они используют эти выражения? Просто для предпочтения. Function.identity()
Метод всегда будет возвращать один и тот же экземпляр. Итак, используя Function.identity()
вместо i -> i
может сэкономить память Тем не мение, i -> i
более читабельно, чем Function.identity()
но поскольку создает свой собственный экземпляр и имеет отдельный класс реализации, потребляет больше памяти. ::
Лямбда-выражение - это просто захват ссылки на метод.
Но как я могу применить это к моему решению?
Ну вот так:
final List<String> list;
...
// list initialization;
list = br.lines().collect(Collectors.toList());
...
Map<Integer, String> fileNumWithContentMapper = IntStream
.range(0, list.size()) // IntStream
.boxed() // Stream<Integer>
.collect(Collectors.toMap(i -> i, i -> list.get(i))); // Map<Integer, String>
альтернативаfinal List<String> list;
...
// list initialization;
list = br.lines().collect(Collectors.toList());
...
Map<Integer, String> fileNumWithContentMapper = IntStream
.range(0, list.size()) // IntStream
.boxed() // Stream<Integer>
.collect(Collectors.toMap(Function.identity(), list::get)) // Map<Integer, String>
Ты можешь использовать IntStream.range
:
IntStream.range(0, list.size())
.boxed()
.collect(Collectors.toMap(Function.identity(), i -> list.get(i)));
Другой вариант будет использовать LineNumberReader
API.
Попробуйте этот код:
public static void main(String[] args) {
List<String> list = Arrays.asList("A", "B", "C");
list.forEach( System.out::println );
AtomicInteger i = new AtomicInteger(0);
Map<Integer, String> fileNumWithContentMapper = list.stream()
.collect( Collectors.toMap( n->i.incrementAndGet(),s1->s1));
System.out.println(fileNumWithContentMapper);
}
Предположим, у вас есть List
как ниже:
List<String> list = Arrays.asList("Vishwa","Ram","Mohan","Sohan");
Теперь вы хотите вывод, как показано ниже:
0 Vishwa
1 Ram
2 Mohan
3 Sohan
public class Someclass{
static int j=0;
static int count(int de){
return de++;
}
public static void main(String[] args) {
List<String> list = Arrays.asList("Vishwa","Ram","Mohan","Sohan");
Map<Integer,String> map;
map = list.stream().collect(Collectors.toMap(s->{count(j);return j++;}, Function.identity()));
map.forEach((k,v)-> {
System.out.print(k+" ");
System.out.println(v);
});
}
}
Stream.of("A", "B", "C").collect(TreeMap<Integer, String>::new
,(map, element) -> map.put(Optional.ofNullable(map.lastEntry()).map(e -> e.getKey() + 1).orElse(1), element)
,(m1, m2) -> {})
.forEach((i, e) -> System.out.println(i + " " + e));
Печать:
1 A
2 B
3 C