如何在不创建新对象的情况下修剪java中的字符串?

时间:2017-02-03 11:10:17

标签: java string trim

我有一个大文本文件(大约2000万行),其中包含以下格式的行:

<string1>, <string2>

现在这些字符串可能有尾随或前导空格,我想在读取文件时将其删除。

我目前正在使用trim()来实现此目的,但由于Java中的String是不可变的,trim()正在为每个trim操作创建一个新对象。 这导致了太多的内存浪费。

我怎样才能做得更好?

7 个答案:

答案 0 :(得分:2)

如果不可变的String类导致问题,我会感到惊讶; JVM非常高效,是多年工程工作的结果。

也就是说,Java确实为操作名为StringBuilder的字符串提供了一个可变类。您可以阅读文档here

如果您正在跨线程工作,consider using StringBuffer

答案 1 :(得分:0)

您可以将字符串作为字符串读取,并记录要解析的每个标记的开始和结束位置。

这仍然会为每个标记创建一个对象,但如果您的标记相对较长,则对象将包含的两个int字段比相应的字符串小得多。

但是在你开始这段旅程之前,你应该确保你没有把修剪好的琴弦放在比需要更长的时间。

答案 2 :(得分:0)

假设您有String包含<string1>, <string2>,并且您只是想拆分它而不修剪部分:

String trimmedBetween(String str, int start, int end) {
  while (start < end && Character.isWhitespace(str.charAt(start)) {
    ++start;
  }

  while (start < end && Character.isWhitespace(str.charAt(end - 1)) {
    --end;
  }

  return str.substring(start, end);
}

(请注意,这基本上是String.trim()的实施方式,仅使用startend代替0length

然后打电话给:

int commaPos = str.indexOf(',');
String firstString = trimmedBetween(str, 0, commaPos);
String secondString = trimmedBetween(str, commaPos + 1, str.length());

答案 3 :(得分:0)

正如您已经注意到的,字符串是不可变的。所以解决方案是不使用String,而是使用可变的东西。 StringBuffer是一个合适的班级。

但是,StringBuffer不包含trim方法,因此您可以使用类似:

的内容
void trim(StringBuffer sb) {
    int start = 0;
    while (sb.length() > start && Character.isWhitespace(sb.charAt(0))) {
        start++;
    }
    sb.delete(0, start - 1);

    int end = 0;
    while (sb.length() > end && Character.isWhitespace(sb.charAt(sb.length() - 1))) {
        end++;
    }
    sb.delete(sb.length() - end, sb.length() - 1);
}

答案 4 :(得分:0)

如果您想避免使用String,则必须使用charStringBuilder自行处理,如下所示:

public class Test {
    public static void main(String... args) throws Exception {
        InputStreamReader in = new InputStreamReader(new FileInputStream("<testfile>"), "UTF-8");

        char[] buffer = new char[32768];
        int read = -1;
        int index;
        StringBuilder content = new StringBuilder();
        while ((read = in.read(buffer)) > -1) {
            content.append(buffer, 0, read);
            index = 0;
            while (index > -1) {
                index = content.indexOf("\n");
                if (index > -1) {
                    char[] temp = new char[index];
                    content.getChars(0, index, temp, 0);
                    handleLine(temp);
                    content.replace(0, index + 1, "");
                }
            }
        }

        in.close();
    }

    private static void handleLine(char[] line) {
        StringBuilder content = new StringBuilder().append(line);
        int start = 0;
        int end = content.length();
        if (end > 0) {
            char ch = content.charAt(0);
            while (Character.isWhitespace(content.charAt(start))) {
                start++;
                if (end <= start) {
                    break;
                }
            }
            if (start < end) {
                while (Character.isWhitespace(content.charAt(end - 1))) {
                    end--;
                    if (end <= start) {
                        break;
                    }
                }
            }
        }

        System.out.println("***" + content.subSequence(start, end) + "***");
    }
}

答案 5 :(得分:0)

我们可以通过Regex处理。

   {
    String str = "abcd, efgh";
    String [] result = str.split("(,\\s)|,");
    Arrays.asList(result).forEach(s -> System.out.println(s));
   }

答案 6 :(得分:-1)

我认为您可以直接将结果数据写入新文件。

String originStr = "   xxxxyyyy";
for (int i = 0; i < originStr.length(); i++) {
    if (' ' == originStr.charAt(i)) {
        continue;
    }
    NewFileOutPutStream.write(originStr.charAt(i));
}