首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java 9中压缩字符串与压缩字符串的区别

Java 9中压缩字符串与压缩字符串的区别
EN

Stack Overflow用户
提问于 2017-05-25 10:38:21
回答 4查看 8.1K关注 0票数 67

紧串相对于JDK9中的压缩字符串有什么优势?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-05-25 11:22:06

压缩字符串(Java 6)和紧凑字符串(Java 9)具有相同的动机(字符串通常实际上是拉丁语-1,因此一半的空间被浪费了)和目标(使这些字符串变小),但实现有很大不同。

压缩串

一次采访中,Aleksey Shipil v(负责实现Java9特性)对压缩字符串有这样的说法:

UseCompressedStrings特性相当保守:在区分char[]byte[]情况,并试图将char[]压缩为byte[] on String构造时,它在char[]上执行了大多数String操作,因此需要解压String.,因此它只受益于一种特殊类型的工作负载,其中大多数字符串是可压缩的(因此压缩不会浪费),并且只对它们执行有限的已知String操作(因此不需要解打包)。在许多工作负载中,启用-XX:+UseCompressedStrings是一种悲观。 ..。UseCompressedStrings实现基本上是一个可选特性,它在alt-rt.jar中维护一个完全不同的String实现,在提供VM选项后加载该实现。可选特性很难测试,因为它们是要尝试的选项组合数量的两倍。

紧串

另一方面,在Java 9中,紧凑型字符串完全集成到JDK源代码中。String总是由byte[]支持,如果字符是拉丁文-1,则字符使用一个字节,否则是两个字节。大多数操作都会检查是什么情况,例如charAt

代码语言:javascript
复制
public char charAt(int index) {
    if (isLatin1()) {
        return StringLatin1.charAt(value, index);
    } else {
        return StringUTF16.charAt(value, index);
    }
}

在默认情况下可以启用紧凑型字符串,并且可以部分禁用--“部分”因为它们仍然由byte[]支持,返回chars的操作仍然必须将它们从两个单独的字节中组合起来(由于本质原因,很难说这是否会对性能产生影响)。

更多

如果您对紧凑字符串的更多背景感兴趣,我建议您阅读上面链接的采访和/或查看这个伟大的演讲是由同样的Aleksey Shipil v (这也解释了新的字符串连接)。

票数 74
EN

Stack Overflow用户

发布于 2017-05-25 10:57:24

XX:+UseCompressedStrings和紧凑型字符串是不同的东西。

UseCompressedStrings意味着只有ASCII的字符串可以转换为byte[],但默认情况下是关闭的。在jdk-9中,这种优化总是开着的,但不是通过标志本身,而是通过内置的。

直到java-9字符串在内部以UTF-16编码形式存储为char[]。从java-9到更高版本,它们将被存储为byte[]。为什么?

因为在ISO_LATIN_1中,每个字符都可以用一个字节(8位)进行编码,相对于到目前为止它以前的情况(16位,每个字符中有8个从未使用过)。这只适用于ISO_LATIN_1,但这是大多数String使用的方式。

所以这是为了空间的使用。

下面是一个小例子,应该让事情变得更清楚:

代码语言:javascript
复制
class StringCharVsByte {
    public static void main(String[] args) {
        String first = "first";
        String russianFirst = "первыи";

        char[] c1 = first.toCharArray();
        char[] c2 = russianFirst.toCharArray();

        for (char c : c1) {
            System.out.println(c >>> 8);
        }

        for (char c : c2) {
            System.out.println(c >>> 8);
        }
    }
}

在第一种情况下,我们将只得到零,这意味着最重要的8位是零;在第二种情况下,将有一个非零的值,这意味着从最重要的8中至少有一位是存在的。

这意味着,如果在内部将string存储为一个字符数组,则会有字符串文本实际上浪费了每个字符的一半。事实证明,由于这一点,许多应用程序实际上会浪费大量的空间。

你有由10个Latin1字符组成的字符串吗?你刚刚损失了80位,或者说10字节。为了减轻此字符串压缩,进行了压缩。现在,这些字符串不会有空间损失。

在内部,这也意味着一些非常好的事情。为了区分为LATIN1UTF-16的字符串,有一个字段coder

代码语言:javascript
复制
/**
 * The identifier of the encoding used to encode the bytes in
 * {@code value}. The supported values in this implementation are
 *
 * LATIN1
 * UTF16
 *
 * @implNote This field is trusted by the VM, and is a subject to
 * constant folding if String instance is constant. Overwriting this
 * field after construction will cause problems.
 */
private final byte coder;

现在,根据这个length进行不同的计算:

代码语言:javascript
复制
public int length() {
    return value.length >> coder();
}

如果我们的字符串仅为Latin1,则编码器将为零,因此值的长度(字节数组)是字符的大小。对于非拉丁1除以二。

票数 27
EN

Stack Overflow用户

发布于 2017-05-25 11:14:28

紧凑型弦将有最好的两个世界。

在OpenJDK文档中提供的定义中可以看到:

新的string类将根据字符串的内容存储编码为ISO-8859-1/拉丁文-1(每个字符一个字节)或UTF-16 (每个字符两个字节)的字符。编码标志将指示所使用的编码。

正如@Eugene所提到的,大多数字符串以拉丁文1格式编码,每个字符需要一个字节,因此不需要当前String类实现中提供的全部2字节空间。

新的String类实现将从UTF-16 char array转移到a byte array 加上编码标志字段。附加的编码字段将显示字符是使用UTF-16还是拉丁文-1格式存储的。

这也得出结论,如果需要的话,我们还可以以UTF-16格式存储字符串。这也成为Java 6压缩字符串与压缩字符串Java 9的主要区别之处,因为压缩字符串中只使用byte[]数组进行存储,然后将其表示为纯ASCII。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44178432

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档