[英]How to auto increment the key of a hashmap using collectors and stream in java 8
我是 Java 8: Streams
和Collectors
类的新手。
我正在读取一个文件,其内容需要保存在LinkedHashMap<Integer, String>
,其中<keys>
是文件的行号,它的<values>
是每一行的内容。
在这里,我想使用Stream
概念,但我无法使用Collectors.toMap
自动递增<keys>
,需要保存在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));
有很多方法可以做到这一点。 但在这里我将解释我的方式:
IntStream
对象的大小。 首先,只要您有一个List<E>
对象(即E
可以是String
、 Integers
、 Objects
等),您就可以使用IntStream
类将其转换为Map<Integer, E>
。 此类是支持顺序和并行聚合操作的原始整数值元素序列。 这意味着就像一个巨大的计数器。 如果我们已经有一个计数器,我们需要设置一些限制, IntStream.range(int start, int end)
方法将帮助我们。 此方法将通过增量步长 1 返回从start
(包含)到end
(不包含)的顺序有序IntStream
。因此,如果您想创建一个具有我们List
大小的IntStream
,请使用以下命令:
List<Integer> numbers = Arrays.asList(4, 5, 4, 3);
IntStream stream = IntStream.range(0, numbers.size);
IntStream
对象准备一个Stream
对象。 现在,我们有一个List<E>
大小的计数器,但我们需要一个Map<Integer, E>
。 好吧,现在我们要使用IntStream.boxed()
。 此方法返回一个Stream
,该Stream
由该流的元素组成,每个元素都装箱为一个Integer
。 这是一个Stream<Integer>
。 我们快完成了。
Stream<Integer> streamBoxed = stream.boxed();
Stream
对象转换为Map
对象最后,我们可以使用Stream.collect()
方法创建地图。 此方法对此流的元素执行可变归约操作。 如果我们没有Collectors.toMap()
方法的帮助,这种减少会很复杂。 此收集器可用于将 Stream 元素收集到 Map 实例中。 为此,我们需要提供两个函数: keyMapper
和valueMapper
。 keyMapper
将用于从Stream
元素中提取Map
键, valueMapper
将用于提取与给定<key>
关联的<value>
<key>
。 对于我们的示例,我们将使用Map<Integer, Integer>
。 keyMapper
将使用i -> i
提取我们可以提取的steamBoxed
流的值,而valueMapper
应该是我们将获得的numbers
列表的值,使用i -> numbers.get(i)
像这样:
Map<Integer, Integer> result = streamBoxed.collect(Collectors.toMap(i -> i, i -> numbers.get(i)))
这三个部分可以在这个简单的代码中组合在一起:
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
lambda 表达式用作valueMapper
。 他们为什么使用这些表达? 只是为了偏好。 Function.identity()
方法将始终返回相同的实例。 因此,使用Function.identity()
而不是i -> i
可能会节省一些内存。 但是, i -> i
比Function.identity()
更具可读性,但是因为创建自己的实例并具有不同的实现类会消耗更多内存。 ::
lambda 表达式只是一个方法引用捕获。
嗯,像这样:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.