迭代Java String的最佳方法是什么?

时间:2012-02-13 11:06:38

标签: java string

目前我使用的是:

String[]lines = textContent.split(System.getProperty("line.separator"));
for(String tmpLine : lines){
   //do something
}

我对这种方法不是很满意,因为它创建了一个沉重的数组(假设textContent可以包含一本书)。

是否有更好的解决方案来迭代String的行?

10 个答案:

答案 0 :(得分:56)

您可以使用:

BufferedReader bufReader = new BufferedReader(new StringReader(textContent));

并使用readLine()方法:

String line=null;
while( (line=bufReader.readLine()) != null )
{

}

答案 1 :(得分:19)

将Java 8方式添加到此问题:

Arrays.stream(content.split("\\r?\\n")).forEach(line -> /*do something */)

如果你确定该文件来自与运行vm相同的平台,你也可以使用System.lineSeparator()进行分割。

甚至更好地使用流api甚至更多agressiv与过滤器,地图和收集:

String result = Arrays.stream(content.split(System.lineSeparator()))
                     .filter(/* filter for lines you are interested in*/)
                     .map(/*convert string*/)
                     .collect(Collectors.joining(";"));

答案 2 :(得分:6)

您可以使用String.indexOf()/ String.substring()

String separator = System.getProperty("line.separator");
int index = textContent.indexOf(separator);

while (index > 0)
{
  int nextIndex = textContent.indexOf(separator, index + separator.length());
  String line = textContent.substring(index + separator.length(), nextIndex);

  // do something with line.
}

答案 3 :(得分:5)

Scanner

Java 1.5中添加的java.util.Scanner类怎么样?

总结:

  

一个简单的文本扫描程序,可以解析基本类型和字符串   使用正则表达式。

     

扫描仪使用分隔符模式将其输入分解为标记,   默认情况下匹配空格。然后可以得到所产生的令牌   使用各种下一个转换为不同类型的值   方法

并注意您的方案:

  

扫描仪还可以使用空格以外的分隔符。这个   示例从字符串中读取几个项目:

     String input = "1 fish 2 fish red fish blue fish";
     Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
     System.out.println(s.nextInt());
     System.out.println(s.nextInt());
     System.out.println(s.next());
     System.out.println(s.next());
     s.close();

答案 4 :(得分:5)

Guava的Splitter效果很好。特别是你可以删除空行

Splitter splitter = Splitter.on(System.getProperty("line.separator"))
                            .trimResults()
                            .omitEmptyStrings();
for (String line : splitter.split(input)){
   // do work here
}

答案 5 :(得分:2)

您实际上可以与Scanner争吵,以允许您使用正常的for循环:

import java.util.Scanner;
public class IterateLines {
    public static void main(String[] args) {
        Iterable<String> sc = () ->
            new Scanner("foo bar\nbaz\n").useDelimiter("\n");
        for (String line: sc) {
            System.out.println(line);
        }
    }
}

给我们:

$ javac IterateLines.java && java IterateLines 
foo bar
baz

答案 6 :(得分:1)

将BufferedReader与StringReader参数一起使用。 BufferedReader有一个方法readLine(),所以你可以逐行读取你的字符串。

    StringReader reader = new StringReader(myBigTextString);
    BufferedReader br = new BufferedReader(reader);
    String line;
    while((line=br.readLine())!=null)
    {
        //do what you want
    }

答案 7 :(得分:1)

合并java.io.StringReaderjava.io.LineNumberReader

答案 8 :(得分:1)

我相信您可以使用JDK / 11获得更好的API,您可以使用 String.lines() API执行相同操作,该API返回从此字符串中提取的字符串流,这些字符串由行终止符分区

public Stream<String> lines()

相同的用法可能是: -

Stream<String> linesFromString = textContent.lines();
linesFromString.forEach(l -> { 
    //do sth
});

重要API说明 : -

@implNote This method provides better performance than
          split("\R") by supplying elements lazily and
          by faster search of new line terminators.

答案 9 :(得分:1)

如果您使用的是Java 1.8(或Android),请尝试以下操作:

new BufferedReader(new StringReader(str)).lines().forEachOrdered((line) -> {
    // process each line as you like
});

Docs state

该流是延迟填充的,即在终端流操作期间只读发生。

这意味着它的运行速度比其他解决方案要快,其他解决方案在迭代开始之前先生成大量的Strings。

如果您使用的是Java 11或更高版本,那么@Naman推荐String#lines()方法的答案也更加简洁,快速,请参阅https://stackoverflow.com/a/50631579/215266