【问题标题】:Access a character in a string that has more than 2^31 characters访问字符串中超过 2^31 个字符的字符
【发布时间】:2019-05-03 07:50:37
【问题描述】:

我一直在尝试从具有 1 万亿个字符的字符串中访问一个字符。我正在使用 BigInteger 从字符串中获取索引号,并使用 charAt 方法从字符串中访问字符。

我要做的是计算给定字符串中特定字符的出现次数。

例如,字符串:aaaaaaa...最多 1 万亿个字符的“a”。然后我将计算字符'a'的出现(要计算的给定字符)

如何访问超过 2,147,483,647 (2^31) 的字符串中的字符?有没有其他方法可以做到这一点?

代码片段:

BigInteger String_Length = BigInteger.valueOf(n); //1,000,000,000,000
    BigInteger Occurence = BigInteger.valueOf(0);

    StringBuilder sb = new StringBuilder();
    char c; 

    for(BigInteger First_Counter = BigInteger.valueOf(0); First_Counter.compareTo(String_Length) <= 0; First_Counter = First_Counter.add(BigInteger.ONE)){
        for(BigInteger Char_Counter = BigInteger.valueOf(0); Char_Counter.compareTo(String_Length) <= 0; Char_Counter = Char_Counter.add(BigInteger.ONE)){
            c = s.charAt(Char_Counter);
            c = sb.append(c);
        }
    }

    for(BigInteger Second_Counter = BigInteger.valueOf(0); Second_Counter.compareTo(String_Length) <= 0; Second_Counter = Second_Counter.add(BigInteger.ONE)){
        c = sb.charAt(Second_Counter); 

        if(c == 'a')
            Occurence = Occurence.add(BigInteger.ONE);

    }

错误

  1. 错误:找不到适合 charAt(BigInteger) 的方法 c = s.charAt(Char_Counter);
  2. 方法 CharSequence.charAt(int) 不适用 (参数不匹配;BigInteger 无法转换为 int)
  3. 错误:不兼容的类型:StringBuilder 无法转换为 char c = sb.append(c);

【问题讨论】:

  • 字符串不能超过Integer.MAX_VALUE 个字符。
  • 错误信息中有什么不清楚的地方? charAt() 需要一个 int。你正在传递一个 BigInteger。 BigInteger 不是 int。所以这不可能编译。就这么简单。
  • 在处理此类问题时,您需要做一些基本的数学运算。 1 万亿个字符,即使假设字符串每个字符只使用一个字节,也需要 1000 GB 的 RAM。你有吗?
  • 如前所述,Java 中的字符串不能长于 Integer.MAX_VALUE (而且它们的长度还受到您可以达到的最大堆大小除以 2 的限制)。
  • @JoeC 也许他在处理人类基因组 :) 人类基因组有超过 60 亿个碱基

标签: java string char stringbuilder biginteger


【解决方案1】:

java.lang.String 不适合非常大的字符串。 BigInteger 不适合索引大于 2^31 的字符串 - 使用 long

字符串的构造需要内存中已经存在的数据,所以需要两个副本。更多缓冲区通常会在构造之前调整大小,这需要至少两倍于实际数据大小加上缓冲区中的任何额外容量。

String 字符(通常为 char,但其他字符可用)的进一步内部存储可能不适合您的数据。另外,你想创建一个BigInteger 对象和内部数组来访问每个索引吗?

即使java.nio 使用int 来索引其缓冲区(当前)。

因此,您需要编写自己的BigString,以long 为索引,并由数组数组支持。或者更可能是内存映射 NIO 缓冲区的数组(或 List)。

【讨论】:

  • 或者,OP 可以使用ReaderInputStream 读取数据,而无需将所有内容都保存在内存中。
  • @MarkRotteveel 我假设 OP 有充分的理由一次将其全部存储在内存中。
  • 我更早地猜测 OP 没有考虑在内存中保留超过 2^31-1 的字符串需要多少内存。
  • 我在七八年前处理过由 2 GB 阵列引起的错误。摩尔定律建议我们现在应该看到这些东西的常见用途。这是一个更有趣的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-03
  • 1970-01-01
  • 2017-05-23
相关资源
最近更新 更多