如何在不检查大小或超出范围的情况下获取字符串的前 n 个字符?
Posted
技术标签:
【中文标题】如何在不检查大小或超出范围的情况下获取字符串的前 n 个字符?【英文标题】:How do I get the first n characters of a string without checking the size or going out of bounds? 【发布时间】:2010-12-07 17:21:42 【问题描述】:如何在不先进行大小检查(可以接受内联)或冒IndexOutOfBoundsException
的风险的情况下获取 Java 中字符串的第一个 n
字符?
【问题讨论】:
除非你捕捉到异常,否则我不知道你打算如何处理字符长度大于字符串长度的情况。 为什么?您对检查长度或捕获异常有什么反感? 出于好奇,为什么要避免尺寸检查。这不是 C。 我的意思是希望避免使用 if/else 块,而不是厌恶实际检查长度。 可能重复:***.com/questions/8499698/… 【参考方案1】:使用substring方法,如下:
int n = 8;
String s = "Hello, World!";
System.out.println(s.substring(0,n);
如果 n 大于字符串的长度,这将引发异常,正如一位评论者所指出的那样。一个简单的解决方案是在else
子句中将所有这些包装在条件if(s.length()<n)
中,您可以选择是只想打印/返回整个字符串还是以其他方式处理。
【讨论】:
这可能会引发 IndexOutOfBoundsException 顺便说一句,如果你打算用 Java 编程,你应该尽量记住 String (java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html) 的大部分 API 方法。 我已经排除了子字符串,至少就其本身而言,作为不是的答案。 您必须检查大小或捕获异常。请问为什么在你的情况下做这两种方法都行不通? 如何回答这个问题?问题是如何不必先进行大小检查,也不会导致需要捕获的异常。【参考方案2】:这是一个巧妙的解决方案:
String upToNCharacters = s.substring(0, Math.min(s.length(), n));
意见:虽然这个解决方案很“简洁”,但我认为它实际上可读性较差比使用if
/ else
的解决方案明显。如果读者没有看到这个技巧,他/她必须更加努力地思考来理解代码。 IMO,代码的含义在if
/else
版本中更明显。有关更清洁/更易读的解决方案,请参阅@paxdiablo 的答案。
【讨论】:
+1。如果这被包装在一个名为 safe_substring 或 substring_safe 的函数中会更好,就像 paxdiablo 的回答一样,这样使用更容易阅读/意图更明显。 我不同意你所说的。如果它被包装在一个函数中,函数内部的内容无关紧要,任何“整洁”肯定会因缺乏清晰度而被压倒。这个解决方案的要点是,对于您不想想要创建包装函数的情况,它是“简洁的”。 使用 StringUtils 会更整洁。它可以防止 IndexOutOfBoundsException 和 NullPointerException。 我不相信防止 NPE 是一件好事。 NPE 意味着您应该在s
中有一个null
。这是错误的标志,而不是应该隐藏的东西。处理 null
不是 OP 规定要求的一部分。【参考方案3】:
有一类关于 SO 的问题有时并不完美,这个问题非常接近 :-)
也许您可以解释您对使用已排除的两种方法之一的厌恶。
如果只是因为您不想在代码中添加if
语句或异常捕获代码,那么一种解决方案是使用一个帮您处理它的辅助函数,例如:
static String substring_safe (String s, int start, int len) ...
这将预先检查长度并采取相应措施(返回较小的字符串或用空格填充)。
那你就完全不用在你的代码中操心了,直接调用:
String s2 = substring_safe (s, 10, 7);
代替:
String s2 = s.substring (10,7);
这适用于您似乎担心的情况(基于您对其他答案的 cmets),在进行大量字符串构建时不会破坏代码流。
【讨论】:
+1:鉴于 OP 不希望代码混乱,这是一种比公认的方法更好的方法。 (或参见 Nickkk 的解决方案,即包含一个已经具有按需要运行的函数的库。)【参考方案4】:不要重新发明***...:
org.apache.commons.lang.StringUtils.substring(String s, int start, int len)
Javadoc 说:
StringUtils.substring(null, *, *) = null StringUtils.substring("", * , *) = ""; StringUtils.substring("abc", 0, 2) = "ab" StringUtils.substring("abc", 2, 0) = "" StringUtils.substring("abc", 2, 4) = "c" StringUtils.substring("abc", 4, 6) = "" StringUtils.substring("abc", 2, 2) = "" StringUtils.substring("abc", -2, -1) = "b" StringUtils.substring("abc", -4, 2) = "ab"
因此:
StringUtils.substring("abc", 0, 4) = "abc"
【讨论】:
它没有回答问题,但无论如何它仍然提供解决方案。如果OP能够理解,我认为这是一个更好的解决方案。 指出StringUtils.substring(yourString, 0, n)
与yourString.substring(0, n)
不同可能也很有用。前者来自StringUtils
,而后者使用String.substring
(如果结束索引超过字符串长度,则会出现异常)。
正如您在查看此方法的源代码时一样,它通过将结尾更改为长度来处理结尾大于长度的情况:if (end > str.length()) end = str.length();
StringUtils.substring(String s, int start, int len)
的最后一个参数不是len,是end-Index。
StringUtils.substring("abc", 0, 4) = "abc",为我工作。谢谢!【参考方案5】:
String upToNCharacters = String.format("%."+ n +"s", str);
如果n
是一个变量,那就太糟糕了(所以你必须构造格式字符串),但如果是一个常量,那就很清楚了:
String upToNCharacters = String.format("%.10s", str);
docs
【讨论】:
有趣的替代方案,虽然我无法想象曾经使用它,考虑到四年前给出的更传统的方法。 最佳答案,因为输入的String只读取一次,所以不需要将其存储在变量中,这样可以整齐地嵌入。【参考方案6】:Apache Commons Lang 对此有一个 StringUtils.left
方法。
String upToNCharacters = StringUtils.left(s, n);
【讨论】:
这不应该是最好的解决方案吗?为什么没有很多人赞成这个? 可能是因为其他人的观点与您不同? :-) 这个答案比原来的提问日期晚了很多。 @DoWill:因为向您的可执行环境添加(其他)第 3 方库并不总是值得的。 @LarsH 但是 Apache Commons,正如它所填充的那样,已经包含在许多项目中。它不会为部分字符串切片添加另一个 3rd 方库。【参考方案7】:ApacheCommons 让我感到惊讶,
StringUtils.abbreviate(String str, int maxWidth)
附加“...”没有更改后缀的选项。
WordUtils.abbreviate(String str, int lower, int upper, String appendToEnd)
查找下一个空白空间。
我将把它留在这里:
public static String abbreviate(String s, int maxLength, String appendToEnd)
String result = s;
appendToEnd = appendToEnd == null ? "" : appendToEnd;
if (maxLength >= appendToEnd.length())
if (s.length()>maxLength)
result = s.substring(0, Math.min(s.length(), maxLength - appendToEnd.length())) + appendToEnd;
else
throw new StringIndexOutOfBoundsException("maxLength can not be smaller than appendToEnd parameter length.");
return result;
【讨论】:
@VolkanGüven 正是因为这句“ApacheCommons 让我感到惊讶”。我通过批评神圣的 ApacheCommons 库犯了罪。或者什么...以上是关于如何在不检查大小或超出范围的情况下获取字符串的前 n 个字符?的主要内容,如果未能解决你的问题,请参考以下文章