从 Java 中的字符串中获取第一个字母的最佳方法是什么,以长度为 1 的字符串形式返回?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18201191/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:14:58  来源:igfitidea点击:

What is the best way to get the first letter from a string in Java, returned as a string of length 1?

javastring

提问by Adrian Torrie

Assume the following:

假设如下:

String example      = "something";
String firstLetter  = "";

Are there differences to be aware of with the following ways of assigning firstLetterthat could impact performance; which would be best, and why?

是否存在以下firstLetter可能影响性能的分配方式的差异需要注意;哪个最好,为什么?

firstLetter = String.valueOf(example.charAt(0));
firstLetter = Character.toString(example.charAt(0));
firstLetter = example.substring(0, 1);

The reason the first letter is being returned as a Stringis that this is being run in Hadoop, and a string is required to assign to a Texttype, firstLetterwill be output as a keyfrom a map()method, for example:

第一个字母作为 a 返回的原因String是它正在 Hadoop 中运行,并且需要一个字符串来分配给一个Text类型,将从一个方法中firstLetter作为 a 输出,例如:keymap()

public class FirstLetterMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
    String line = new String();
    Text firstLetter = new Text();
    IntWritable wordLength = new IntWritable();

    @Override
    public void map(LongWritable key, Text value, Context context)
            throws IOException, InterruptedException {

        line = value.toString();

        for (String word : line.split("\W+")){
            if (word.length() > 0) {

                // ---------------------------------------------
                // firstLetter assignment
                firstLetter.set(String.valueOf(word.charAt(0)).toLowerCase());
                // ---------------------------------------------

                wordLength.set(word.length());
                context.write(firstLetter, wordLength);
            }
        }
  }
}

采纳答案by Ankur Lathi

Performance wise substring(0, 1)is better as found by following:

性能方面substring(0, 1)更好,如下所示:

    String example = "something";
    String firstLetter  = "";

    long l=System.nanoTime();
    firstLetter = String.valueOf(example.charAt(0));
    System.out.println("String.valueOf: "+ (System.nanoTime()-l));

    l=System.nanoTime();
    firstLetter = Character.toString(example.charAt(0));
    System.out.println("Character.toString: "+ (System.nanoTime()-l));

    l=System.nanoTime();
    firstLetter = example.substring(0, 1);
    System.out.println("substring: "+ (System.nanoTime()-l));

Output:

输出:

String.valueOf: 38553
Character.toString: 30451
substring: 8660

回答by yshavit

Long story short, it probably doesn't matter. Use whichever you think looks nicest.

长话短说,这可能无关紧要。使用您认为最好看的那个。

Longer answer, using Oracle's Java 7 JDK specifically, since this isn't defined at the JLS:

更长的答案,特别是使用 Oracle 的 Java 7 JDK,因为这不是在 JLS 中定义的:

String.valueOfor Character.toStringwork the same way, so use whichever you feel looks nicer. In fact, Character.toStringsimply calls String.valueOf(source).

String.valueOf或者Character.toString以同样的方式工作,所以使用你觉得更好看的那个。实际上,Character.toString只需调用String.valueOf( source)。

So the question is, should you use one of those or String.substring. Here again it doesn't matter much. String.substringuses the original string's char[]and so allocates one object fewer than String.valueOf. This also prevents the original string from being GC'ed until the one-character string is available for GC (which can be a memory leak), but in your example, they'll both be available for GC after each iteration, so that doesn't matter. The allocation you save also doesn't matter -- a char[1]is cheap to allocate, and short-lived objects (as the one-char string will be) are cheap to GC, too.

所以问题是,你应该使用其中之一还是String.substring. 这里又没有太大关系。String.substring使用原始字符串char[],因此分配的对象少于String.valueOf. 这也可以防止原始字符串被 GC 处理,直到一个字符的字符串可用于 GC(这可能是内存泄漏),但在您的示例中,它们在每次迭代后都可用于 GC,因此不会没关系。您保存的分配也无关紧要—— achar[1]分配起来很便宜,而且短期对象(如单字符字符串一样)对于 GC 来说也很便宜。

If you have a large enough data set that the three are even measurable, substringwill probably give a slightedge. Like, really slight. But that "if... measurable" contains the real key to this answer: why don't you just try all three and measure which one is fastest?

如果您有足够大的数据集,这三个甚至可以测量,substring则可能会略有优势。喜欢,真的很轻微。但是“如果……可测量”包含了这个答案的真正关键:为什么不尝试所有三个并测量哪个最快?

回答by rohan

import java.io.*;
class Initials {

    public static void main(String args[]) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s;
        char x;
        int l;
        System.out.print("Enter any sentence: ");
        s = br.readLine();
        s = " " + s; //adding a space infront of the inputted sentence or a name
        s = s.toUpperCase(); //converting the sentence into Upper Case (Capital Letters)
        l = s.length(); //finding the length of the sentence
        System.out.print("Output = ");

        for (int i = 0; i < l; i++) {
            x = s.charAt(i); //taking out one character at a time from the sentence
            if (x == ' ') //if the character is a space, printing the next Character along with a fullstop
                System.out.print(s.charAt(i + 1) + ".");
        }
    }
}

回答by MIk.13

String whole = "something";
String first = whole.substring(0, 1);
System.out.println(first);

回答by Nikita

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;

import java.util.concurrent.TimeUnit;

@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5, time = 1)
@Fork(value = 1)
@Measurement(iterations = 5, time = 1)
public class StringFirstCharBenchmark {

    private String source;

    @Setup
    public void init() {
        source = "MALE";
    }

    @Benchmark
    public String substring() {
        return source.substring(0, 1);
    }

    @Benchmark
    public String indexOf() {
        return String.valueOf(source.indexOf(0));
    }
}

Results:

结果:

+----------------------------------------------------------------------+
| Benchmark                           Mode  Cnt   Score   Error  Units |
+----------------------------------------------------------------------+
| StringFirstCharBenchmark.indexOf    avgt    5  23.777 ? 5.788  ns/op |
| StringFirstCharBenchmark.substring  avgt    5  11.305 ? 1.411  ns/op |
+----------------------------------------------------------------------+