Java 字符串等于与字节数组比较

Java 字符串等于与字节数组比较,java,Java,字节数组比较(使用简单循环检查每个索引)是否比使用String.equals(Object)更快?我不这么认为,但有些人似乎更喜欢基于字节的操作,而不是包括字节数组相等性检查在内的基于字符串的操作 在侧节点上,何时使用字节数组而不是字符串有意义?例如,您认为实现Levenshtein算法来计算两个字符串的“距离”的度量吗。如果它基于字节而不是字符串/字符,你认为它会加快计算速度吗?我不这么认为,但也许吧 例如,如果它用于编码标记,如在中所示,字符串不包含字节。它们含有焦炭。字符串equals显然

字节数组比较(使用简单循环检查每个索引)是否比使用
String.equals(Object)
更快?我不这么认为,但有些人似乎更喜欢基于字节的操作,而不是包括字节数组相等性检查在内的基于字符串的操作

在侧节点上,何时使用字节数组而不是字符串有意义?例如,您认为实现Levenshtein算法来计算两个字符串的“距离”的度量吗。如果它基于字节而不是字符串/字符,你认为它会加快计算速度吗?我不这么认为,但也许吧


例如,如果它用于编码标记,如在中所示,字符串不包含字节。它们含有焦炭。字符串equals显然比较了两个字符串的字符(除非它们甚至没有相同的长度)。由于String可以直接访问底层的char数组,而外部代码没有,因此使用
equals
显然更快


在处理二进制数据(二进制流、加密等)时,使用字节数组是有意义的。在处理文本数据时,使用字符串、StringBuilder、CharSequence或char数组更好。这取决于具体情况。

我写了一个小测试来看看,而不是猜测:

import java.util.Arrays;
import java.util.Random;

public class StringComparisons {

    static String[] strings = new String[10000];
    static byte[][] bytes = new byte[10000][];

    public static void main(String[] args) {

        Random r = new Random();
        System.out.println("Generating strings/byte arrays");
        for (int i = 0; i < strings.length; i++) {
            StringBuilder s = new StringBuilder();
            for (int j = 0; j < 1000; j++) {
                s.append(r.nextInt(128) + 1);
            }
            strings[i] = s.toString();
            bytes[i] = strings[i].getBytes();
        }
        final String comparend = strings[r.nextInt(strings.length)];
        final byte[] byteComparend = comparend.getBytes();

        System.out.println("Comparing strings...");
        long start = System.nanoTime();
        for (int i = 0; i < strings.length; i++) {
            comparend.equals(strings[i]);
        }
        long elapsed = System.nanoTime() - start;
        System.out.printf("Comparing strings took %f s\n", (elapsed / 1000000000.0));

        System.out.println("Comparing byte arrays");
        start = System.nanoTime();
        for (int i = 0; i < bytes.length; i++) {
            Arrays.equals(byteComparend, bytes[i]);
        }
        elapsed = System.nanoTime() - start;
        System.out.printf("Comparing bytes took %f s\n", (elapsed / 1000000000.0));
    }
}

您可以对此类基准使用JMH。下面是你问题的一个例子

@BenchmarkMode({ Mode.AverageTime, Mode.Throughput })
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 3, time = 5)
@Measurement(iterations = 5, time = 10)
@Threads(1)
@State(Scope.Benchmark)
public class StringVsBytesComparison {

    String s1 = "Hello";
    String s2 = "Hello";

    @Benchmark
    public boolean stringComparison() {
        String s1 = "Hello";
        String s2 = "Hello";

        return s1.equals(s2);
    }

    @Benchmark
    public boolean bytesComparison() {
        byte[] ba1 = s1.getBytes();
        byte[] ba2 = s2.getBytes();

        return Arrays.equals(ba1, ba2);
    }
}
输出

Benchmark                                  Mode  Cnt   Score   Error   Units
StringVsBytesComparison.bytesComparison   thrpt    5   0.011 ± 0.001  ops/ns
StringVsBytesComparison.stringComparison  thrpt    5   0.466 ± 0.010  ops/ns
StringVsBytesComparison.bytesComparison    avgt    5  90.547 ± 3.312   ns/op
StringVsBytesComparison.stringComparison   avgt    5   2.166 ± 0.062   ns/op
显然字符串比较获胜。
请查找完整的源代码

如果我没记错的话,字符串和字节数组是两个独立的东西,字符是UCS-2或UTF-16之类的。如果是这样的话,你是在问烤面包机是否比食品加工机快。@David在我看来,你的类比有点不恰当。Java
char
s没有什么特别之处。它们只是不带符号的16位整数,不多也不少。它们仍然与字节不同。是的,我知道这不一样,我想知道如果你转换例如令牌,是否有意义,就像为什么将整个字符串复制到字节数组中只是为了比较它们一样?这根本没有道理。字符串写入流(文件、套接字等)时必须转换为字节。IO编写者就是为此而写的。你的方法过于简单,所以它当然会给出这些结果。java中的字符串是不可变的对象,因此可以对它们进行极大的优化。其中一个优化是它们的哈希代码是预计算的。比较两个字符串时,首先比较它们的哈希代码,如果它们不同,则跳过实际字符的比较,因为事先知道它将失败。为了进行真正的测试,您必须编写一个新的类,该类封装字节数组,其行为类似于字符串的不可变对象,并且包含相同类型的优化。严格来说,字节数组之间的字节/字节比较(这是OP要求的)不会比字符串比较快。但是这种用法还是很幼稚的。@MikeNakis:OP就是这么问的。它甚至比OP建议的要快,因为它没有考虑到在比较字节数组之前将字符串转换为字节所需的时间。@MikeNakis:我的方法是试图用一些简单的证据来回答实际问题,证明这种方法是幼稚的。写几行代码回答这个问题花了五分钟时间,而不是一堆假设。@JB Nizet(和damianr)我承认,在我的评论中,以“grated,…”开头的关于在比较字节数组之前将字符串转换为字节的问题,那将是疯狂的,但在我写答案的时候,这个问题并没有包括在内。
Benchmark                                  Mode  Cnt   Score   Error   Units
StringVsBytesComparison.bytesComparison   thrpt    5   0.011 ± 0.001  ops/ns
StringVsBytesComparison.stringComparison  thrpt    5   0.466 ± 0.010  ops/ns
StringVsBytesComparison.bytesComparison    avgt    5  90.547 ± 3.312   ns/op
StringVsBytesComparison.stringComparison   avgt    5   2.166 ± 0.062   ns/op