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

时间:2018-06-26 16:24:32

标签: java java-stream collectors

我不熟悉Java 8:StreamsCollectors类。

我正在读取一个文件,其内容需要保存在LinkedHashMap<Integer, String>中,其中<keys>是文件的行号,而<values>是每一行的内容。

在这里,我想使用Stream的概念,但是我无法使用Collectors.toMap自动递增<keys>,需要将其保存在{{1}中}对象。取而代之的是,我得到了例外。

以下是我正在尝试的代码:

LinnkedHashMap

5 个答案:

答案 0 :(得分:1)

您可以使用IntStream.range

IntStream.range(0, list.size())
         .boxed()
         .collect(Collectors.toMap(Function.identity(), i -> list.get(i)));

另一种选择是使用LineNumberReader API。

答案 1 :(得分:0)

尝试此代码:

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);
}

答案 2 :(得分:0)

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

1。设置IntStream对象的大小。

首先,只要您有List<E>个对象(即E可以是StringIntegersObjects等),就可以对其进行转换使用Map<Integer, E>类将其转换为IntStream。此类是一系列原始整数值元素,它们支持顺序和并行聚合操作。这意味着就像一个巨大的柜台。如果我们已经有一个计数器,则需要设置一些限制,IntStream.range(int start, int end)方法将为我们提供帮助。此方法将以1的增量步从IntStream(包括)向start(不包括)返回顺序的end。因此,如果要使用我们IntStream的大小使用以下方法:

List

2。根据{{​​1}}对象准备一个List<Integer> numbers = Arrays.asList(4, 5, 4, 3); IntStream stream = IntStream.range(0, numbers.size); 对象。

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

Integer

3。将Stream<Integer>对象转换为Stream<Integer> streamBoxed = stream.boxed(); 对象

最后,我们可以使用Stream方法创建地图。此方法对该流的元素执行可变还原操作。如果没有Map方法的帮助,这种减少将变得很复杂。该收集器可用于将Stream元素收集到Map实例中。为此,我们需要提供两个功能:Stream.collect()Collectors.toMap()keyMapper将用于从valueMapper元素中提取keyMapper键,Map将被用于提取与给定{{ 1}}。对于我们的示例,我们将使用StreamvalueMapper将是我们可以使用<value>提取的<key>流的值,而Map<Integer, Integer>应该是我们将获得的keyMapper列表的值像这样使用steamBoxed的人:

i -> i

4。结合所有步骤

这三个部分可以通过以下简单代码组合在一起:

valueMapper

此外,您还会发现一些作者更喜欢将numbers方法用作i -> numbers.get(i),而将Map<Integer, Integer> result = streamBoxed.collect(Collectors.toMap(i -> i, i -> numbers.get(i))) lambda表达式用作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可以节省一些内存。但是,valueMapperFunction.identity()更具可读性,但是因为创建自己的实例并具有不同的实现类会消耗更多的内存。 Function.identity() lambda表达式只是方法参考捕获。

但是,如何将其应用于我的解决方案?

好吧,像这样:

i -> i
另类
i -> i

答案 3 :(得分:0)

假设您有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);
    });
    }
}

答案 4 :(得分:0)

SELECT users.name, messages.message
FROM users, messages
WHERE messages.from_id = 1 OR messages.to_id = 1
GROUP BY ??
ORDER BY messages.id DESC

打印:

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));