Java streams修改字符串列表以仅保留每个字符串的子字符串

Java streams修改字符串列表以仅保留每个字符串的子字符串,java,regex,string,java-stream,Java,Regex,String,Java Stream,我试图修改字符串列表,以仅保留每个字符串的子字符串。以下是我想做的: List<String> paychecks = new ArrayList<>(); paychecks.add("Paycheck_Box_EMP_61299_451"); paychecks.add("Paycheck_Box_EMP_5512_221"); paychecks.add("Paycheck_Box_EMP_99993_881&quo

我试图修改字符串列表,以仅保留每个字符串的子字符串。以下是我想做的:

List<String> paychecks = new ArrayList<>();
paychecks.add("Paycheck_Box_EMP_61299_451");
paychecks.add("Paycheck_Box_EMP_5512_221");
paychecks.add("Paycheck_Box_EMP_99993_881");
paychecks.add("Paycheck_Box_EMP_831_141");

paychecks.replaceAll(paycheck -> paycheck.subString("insert here"))

更新(第二次尝试):

抛出错误:

    java.lang.StringIndexOutOfBoundsException: begin 0, end -1, length 26   
    at java.base/java.lang.String.checkBoundsBeginEnd(String.java:3319)
    at java.base/java.lang.String.substring(String.java:1874)

就我个人而言,我不擅长写作,更不擅长阅读正则表达式,因此我不想让替换变得高效,而是优先考虑人类的可读性

除非我考虑修改一组非常大的数据,否则我会执行以下操作:

List<String> paychecks = new ArrayList<>();
paychecks.add("Paycheck_Box_EMP_61299_451");
paychecks.add("Paycheck_Box_EMP_5512_221");
paychecks.add("Paycheck_Box_EMP_99993_881");
paychecks.add("Paycheck_Box_EMP_831_141");
    

paychecks.replaceAll(person -> person
                                .replaceFirst("^Paycheck_Box_EMP_", "") // remove prefix
                                .replaceFirst("_.*$", ""));             // remove suffix

    
System.out.println(paychecks);      // [61299, 5512, 99993, 831]
List paychecks=new ArrayList();
工资支票。添加(“工资支票盒”EMP 61299_451);
工资支票。添加(“工资支票盒”EMP_5512_221);
工资支票。添加(“工资支票盒”EMP 993_881);
工资支票。添加(“工资支票盒”EMP_831_141);
工资支票。全部替换(个人->个人
.replaceFirst(“^Paycheck\u Box\u EMP\uuux”,”)//删除前缀
.replaceFirst(“.*$”,“);//删除后缀
System.out.println(工资支票);//[61299, 5512, 99993, 831]
您可以进一步细化前缀和后缀regexp,具体取决于您对格式的了解程度


例如,在更新的问题中,前缀始终是常量,因此可以使用简单的
replace()
调用。同样,如果你知道后缀总是数字的,你可以使用
[0-9]*
而不是
*
如果我正确理解了任务,你想从
工资支票盒中获得

所以你不想替换一些东西,你想要的是提取一些东西,对吗

这应该是这样的:

[61299, 5512, 99993, 831]
List<String> paychecks = new ArrayList<>();
paychecks.add( "Paycheck_Box_EMP_61299_451" );
paychecks.add( "Paycheck_Box_EMP_5512_221" );
paychecks.add( "Paycheck_Box_EMP_99993_881" );
paychecks.add( "Paycheck_Box_EMP_831_141" );

final var pattern = Pattern.compile( "Paycheck_Box_EMP_(\\d{3,5})_\\d{3}" );
paychecks = paychecks.stream()
  .map( paycheck -> pattern.matcher( paycheck ) )
  .filter( matcher -> matcher.find() )
  .map( matcher -> group( 1 ) )
  .collect( Collectors.toList() );

修复了基于Alex Rudenko的评论的Java。

您可以使用正则表达式,
工资支票盒\u EMP(\d+).*
并用组(1)替换字符串

演示:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<String> paychecks = new ArrayList<>();
        paychecks.add("Paycheck_Box_EMP_61299_451");
        paychecks.add("Paycheck_Box_EMP_5512_221");
        paychecks.add("Paycheck_Box_EMP_99993_881");
        paychecks.add("Paycheck_Box_EMP_831_141");

        List<String> substrs = 
                paychecks.stream()
                        .map(s -> s.replaceAll("Paycheck_Box_EMP_(\\d+).*", "$1"))
                        .collect(Collectors.toList());

        System.out.println(substrs);
    }
}
[61299, 5512, 99993, 831]
正则表达式的解释如下:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<String> paychecks = new ArrayList<>();
        paychecks.add("Paycheck_Box_EMP_61299_451");
        paychecks.add("Paycheck_Box_EMP_5512_221");
        paychecks.add("Paycheck_Box_EMP_99993_881");
        paychecks.add("Paycheck_Box_EMP_831_141");

        List<String> substrs = 
                paychecks.stream()
                        .map(s -> s.replaceAll("Paycheck_Box_EMP_(\\d+).*", "$1"))
                        .collect(Collectors.toList());

        System.out.println(substrs);
    }
}
[61299, 5512, 99993, 831]

试着这样做:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<String> paychecks = new ArrayList<>();
        paychecks.add("Paycheck_Box_EMP_61299_451");
        paychecks.add("Paycheck_Box_EMP_5512_221");
        paychecks.add("Paycheck_Box_EMP_99993_881");
        paychecks.add("Paycheck_Box_EMP_831_141");

        List<String> substrs = 
                paychecks.stream()
                        .map(s -> s.replaceAll("Paycheck_Box_EMP_(\\d+).*", "$1"))
                        .collect(Collectors.toList());

        System.out.println(substrs);
    }
}
[61299, 5512, 99993, 831]
  • 步骤1:删除目标子字符串e.i的前缀工资支票盒\u EMP\u61299\u 451 然后是临时结果子字符串:61299_451

  • 步骤2:删除目标子字符串e.i 61299的后缀_451,子字符串的最终结果将是61299

    工资支票。全部替换(x->x) .replaceFirst(“^Paycheck\u Box\u EMP\uuux”,”) .replaceFirst(“..*$”,“)


您的第二次尝试几乎是对的,这是最简单的方法:

String prefix = "Paycheck_Box_EMP_"; // or use 17 instead of prefix.length()

paychecks.replaceAll(paycheck ->
        paycheck.replaceAll(paycheck, paycheck.substring(prefix.length(), paycheck.lastIndexOf('_'))));

您与使用
subString()
的关系如何?仅仅使用
replaceAll()
和一个regexp模式可能会更干净。我不是太已婚哈哈,但是什么是regex模式来忽略两件事之间的一切呢?事实上,我发现将其分为两个调用更具可读性,一个用于修剪前端,另一个用于修剪后端,例如
people.replaceAll(person->person.replaceAll(“^.*EMP_u“,”).replaceAll(“.*$”,”)
哦,你基本上是在EMP之前和第二次EMP之后删除所有内容吗?太好了,非常感谢你了,我现在就知道了,或者在一次替换操作中,
paychecks.replaceAll(p->p.replaceFirst(“^Paycheck\u Box\u EMP(\\d+).*,“$1”))
您还可以考虑匹配前缀在这里是否很重要,并决定只提取第一个数字:
paychecks.replaceAll(p->p.replaceFirst(“.*”(\\d+).*”,“$1”);
这不起作用,
线程“main”中的异常java.lang.IllegalStateException:未找到匹配项
。您应该通过
flatMap
paychecks=paychecks.stream().flatMap(paycheck->pattern.matcher(paycheck).results().map(mr->mr.group(1)).Collector(Collectors.toList())
问题在于Java代码,而不是regexp,我想,
Matcher::find
Matcher::matches
必须在调用
Matcher::group
之前被调用!这里的常见错误是……重用一个准备好的
模式是一个很好的优化,不过,它的使用不必那么复杂ted.
paychecks.replaceAll(paycheck->pattern.matcher(paycheck.replaceFirst($1));
将提取第一组。