假设我有一个列表:
List<String> dest = Arrays.asList(
"abc abd 2000",
"idf owe 1200",
"jks ldg 789",
"ccc hhh 2000",
"www uuu 1000"
);
我试着得到每个字符串末尾的数字,给定的列表中只有整数,但我也写了double的正则表达式:(\\d+\\.?\\d+)
。在Java 1.8中,我编写了以下代码:
ArrayList<String> mylist = new ArrayList<>(
dest.stream()
.filter(Pattern.compile("\\D+\\s\\D+\\s(\\d+\\.?\\d+)").asPredicate())
.collect(Collectors.toList())
);
我想做的是-从每个找到的字符串中得到(\\d+\\.?\\d+)
组,我该怎么做呢?
我想对列表的每个元素应用一个Matcher
,但是我不确定如何实现它。
4条答案
按热度按时间kkbh8khc1#
我试着得到每一个字符串末尾的数字...
溶液1
也许你可以不使用正则表达式来解决它,就像这样:
溶液2
如果您坚持使用regex,您可以用途:
输出
kpbpu0082#
filter
保留或移除列表中的元素。如果你想转换流元素(当你提取数字时),使用map
。然后,您可以使用正则表达式(沿着
Matcher
)来提取数据:印刷品
mzsu5hc03#
你应该是
.map()
而不是.filter()
。输出:
ohfgkhjo4#
首先,有几个问题值得强调:
filter()
操作开始,这是正确的步骤,因为map()
不能从流中丢弃元素,它执行 * 一对一 * 转换。如果您需要确保元素有效,您需要首先应用filter()
。另一种选择是使用flatMap()
操作,它意味着执行 * 一对多 * 转换。也就是说,它将流元素转换为0+(* 零个或更多 *)个元素,并且可以像filter()
和map()
一样工作。更重要的是,使用flatMap()
可以提高性能,因为它允许避免使用regex引擎两次处理有效字符串(过滤时和Map时)。double
有多个有效的表示:* 指数、十六进制等 *。所有选项都在Double.valueOf()
的文档中列出。即使我们只讨论一个普通十进制浮点数1.
和.9
,它们不是您正在使用的正则表达式,也是有效的double
。注意valueOf()
的Javadoc包含一个 ready-to-go 正则表达式,用于验证双精度数,这是所有可能的挖掘者(它真的很大,充满了评论,所以我不在这里发布它)。$
,表示捕获的字符串应该位于最末尾。ArrayList
PackageCollectors.toList()
返回的List
是多余的。为了简单起见,我将使用下面的正则表达式
"(\\d+\\.?\\d*|\\.\\d+)$"
来代替上面提到的用于检查所有形式的double的正则表达式。第一部分
\\d+\\.?\\d*
将与整数(例如999
)、不具有分数部分的浮点数(例如1.
)和常规浮点数(例如99.999
)匹配。第二部分
\\.\\d+
匹配不带整数部分的浮点数,例如.995
。下面介绍如何使用Stream API特性和
java.util.regex.MatchResult
来实现这一点。***注意:**
Matcher.results()
* 是随Java 9引入的,尽管您提到了Java 8,但我想这个解决方案对其他读者可能有用。另一种方法是使用Java 16
mapMulti()
,它在高级别上的行为几乎与flatMap()
一样,将一个流元素转换为零个或多个元素,但与flatMap()
相反,它的内部机制不需要生成新的流。在这种情况下,流中的每个字符串都需要转换为0或1字符串。如果元素的数量很大,则创建空流和单例流的开销可能会很大。因此,在这种情况下使用
mapMulti()
会更有好处。这就是它可能的实现方式(这个想法归功于 @Holger):