使用Java中的stream().collect创建由2个列表组成的地图
使用Java中的stream().collect创建由2个列表组成的地图
举个例子来说,有两个列表:\n
Listlist1 = Arrays.asList(1.0, 2.0); List list2 = Arrays.asList("one_point_zero", "two_point_zero");
\n使用 Stream,我想要创建一个由这些列表组成的映射,其中 list1 作为键,list2 作为值。为了做到这一点,我需要创建一个辅助列表:\n
Listlist0 = Arrays.asList(0, 1);
\n下面是这个映射:\n
Mapmap2 = list0.stream() .collect(Collectors.toMap(list1::get, list2::get));
\nlist0 被用来使 list1::get 和 list2::get 能够工作。有没有一种更简单的方法,而不需要创建 list0?我尝试了下面的代码,但它没有起作用:\n
Mapmap2 = IntStream .iterate(0, e -> e + 1) .limit(list1.size()) .collect(Collectors.toMap(list1::get, list2::get));
问题的原因:使用list1.indexOf(item)方法在list1中查找item的索引值,如果list1很长或者list1中的元素是复杂值(如String),那么调用indexOf方法会很耗时。
解决方法:使用更高效的方法替代indexOf方法,可以提高性能。
一种解决方法是使用IntStream.range()方法来创建一个索引流,然后使用mapToObj()方法将索引映射为对应的键值对。代码如下:
Mapcollect = IntStream.range(0, list1.size()) .boxed() .collect(toMap(i -> list1.get(i), i -> list2.get(i)));
另一种解决方法是使用IntStream.iterate()方法创建一个索引流,然后使用zip()方法将两个列表合并为一个流,最后使用collect()方法收集为Map。代码如下:
Mapcollect = IntStream.iterate(0, i -> i + 1) .limit(list1.size()) .boxed() .collect(toMap(i -> list1.get(i), i -> list2.get(i)));
这两种方法都避免了使用indexOf方法,提高了性能。
问题的原因是需要将两个列表组合成一个映射(Map),其中第一个列表的元素作为键,第二个列表的元素作为值。同时,需要处理两个列表长度不相等的情况,避免出现IndexOutOfBoundsException异常。
解决方法是使用Java中的流(Stream)和收集器(Collector)操作。首先,使用IntStream.range方法获取一个范围内的整数流,其中范围是从0到两个列表长度的较小值。然后,使用boxed方法将整数流转换为流对象。接下来,使用Collectors.toMap方法将两个列表的元素组合成一个映射,其中第一个列表的元素作为键,第二个列表的元素作为值。最后,通过使用Math.min方法来确保两个列表的长度相等,避免出现IndexOutOfBoundsException异常。
以下是最终的代码示例:
Mapmap2 = IntStream.range(0, Math.min(list1.size(), list2.size())) .boxed() .collect(Collectors.toMap(list1::get, list2::get));
尽管这个解决方法与之前提到的答案本质上相同,但它使用了Math.min方法和::get方法引用(而不是使用lambda表达式),代码看起来更简洁和更安全。
在Java中,我们经常需要创建一个由两个列表组成的映射(Map),其中一个列表用作键,另一个列表用作值。使用Java 8引入的流(stream)和collect方法,我们可以很方便地实现这个目标。
然而,在上述代码中,我们可以看到使用了一个辅助列表来保存索引。这个辅助列表的目的是为了在生成映射时能够通过索引访问两个列表的对应元素。但是,使用辅助列表会增加代码的复杂性和内存消耗。
为了避免使用辅助列表,我们可以使用IntStream来生成索引。IntStream是一个顺序数字流,我们可以通过调用range方法指定起始值和结束值来创建它。在这个例子中,我们使用range方法生成了一个从0到list1的大小的IntStream。
接下来,我们使用boxed方法将IntStream转换为Stream
最后,我们使用collect方法和Collectors.toMap函数来创建映射。toMap函数的第一个参数是键的生成函数,这里我们使用list1中对应索引的元素作为键。toMap函数的第二个参数是值的生成函数,这里我们使用list2中对应索引的元素作为值。
通过这种方法,我们不仅避免了使用辅助列表,而且代码更加简洁和高效。
总结起来,Java中可以通过使用stream()和collect方法来创建由两个列表组成的映射。在上述代码中,我们使用IntStream和Collectors.toMap函数来实现这个目标,并避免了使用辅助列表的复杂性和内存消耗。这种方法不仅简化了代码,还提高了效率。