繁体   English   中英

如何在java 8中使用收集器和流自动增加哈希图的键

[英]How to auto increment the key of a hashmap using collectors and stream in java 8

我是 Java 8: StreamsCollectors类的新手。

我正在读取一个文件,其内容需要保存在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));

有很多方法可以做到这一点。 但在这里我将解释我的方式:

1. 设置一个IntStream对象的大小。

首先,只要您有一个List<E>对象(即E可以是StringIntegersObjects等),您就可以使用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); 

2、根据IntStream对象准备一个Stream对象。

现在,我们有一个List<E>大小的计数器,但我们需要一个Map<Integer, E> 好吧,现在我们要使用IntStream.boxed() 此方法返回一个Stream ,该Stream由该流的元素组成,每个元素都装箱为一个Integer 这是一个Stream<Integer> 我们快完成了。

Stream<Integer> streamBoxed = stream.boxed();

3.将Stream对象转换为Map对象

最后,我们可以使用Stream.collect()方法创建地图。 此方法对此流的元素执行可变归约操作。 如果我们没有Collectors.toMap()方法的帮助,这种减少会很复杂。 此收集器可用于将 Stream 元素收集到 Map 实例中。 为此,我们需要提供两个函数: keyMappervalueMapper 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)))

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 lambda 表达式用作valueMapper 他们为什么使用这些表达? 只是为了偏好。 Function.identity()方法将始终返回相同的实例。 因此,使用Function.identity()而不是i -> i可能会节省一些内存。 但是, i -> iFunction.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM