Скільки символів може мати рядок Java?


157

Я намагаюся задати наступну проблему з паліндромом від Інтернет-судді Sphere (SPOJ), де мені потрібно знайти паліндром на ціле число до мільйона цифр. Я думав про те, щоб використовувати функції Java для обертання рядків, але чи дозволять вони String бути таким довгим?


Ви говорите про те, що вам потрібно написати функцію, яка генерує паліндроми, розмір яких вказаний користувачем і може бути до 1 мільйона символів?
Роберт

3
Проблема (від SPOJ) може містити файл 100Gigabyte, і ви хочете , щоб завантажити його в рядок відразу? Серйозно ... будь ласка, використовуйте сканер!
Грим

Відповіді:


242

Ви повинні мати можливість отримати строку довжини

  1. Integer.MAX_VALUEзавжди 2,147,483,647 (2 31 - 1)
    (Визначено специфікацією Java, максимальний розмір масиву, який використовує клас String для внутрішнього зберігання)
    АБО

  2. Half your maximum heap size(оскільки кожен символ - два байти), залежно від того, який розмір буде меншим .


43
... або ваш максимальний розмір купи, розділений на 2 ... оскільки символ - 2 байти
ChssPly76

2
@ ChssPly76: Так, це правильно. Я відредагував свою відповідь, дякую.
Білл Ящірка

2
як дізнатись максимальний розмір купи? Крім того, я не знаю, яку віртуальну машину Java використовує суддя для перевірки моєї проблеми, чи залежить Integer.MAX_VALUE від специфікації JVM?
andandandand

6
Integer.MAX_VALUE завжди є 2147483647 (2 ^ 31 - 1), це частина специфікації Java.
cd1

4
Якщо припустити 64-розрядний JVM, оскільки для зберігання рядка такої довжини вам знадобиться 8 ГБ віртуальної пам'яті.
Роберт Фрейзер

21

Я вважаю, що їх може бути до 2 ^ 31-1 символів, оскільки їх утримує внутрішній масив, а масиви індексуються цілими числами в Java.


Внутрішня реалізація не має значення - наприклад, немає жодної причини, щоб символьні дані не могли зберігатися в масиві довгих, наприклад. Проблема полягає в тому, що інтерфейс використовує ints для довжини. getBytesі подібні можуть мати проблеми, якщо ви спробуєте дуже велику струну.
Том Хотін - тайклін

Це правда - я мав на увазі цей факт. Моє ліжко.
aperkins

15

Хоча теоретично ви можете використовувати символи Integer.MAX_VALUE, JVM обмежений розміром масиву, який він може використовувати.

public static void main(String... args) {
    for (int i = 0; i < 4; i++) {
        int len = Integer.MAX_VALUE - i;
        try {
            char[] ch = new char[len];
            System.out.println("len: " + len + " OK");
        } catch (Error e) {
            System.out.println("len: " + len + " " + e);
        }
    }
}

оновлення Oracle Java 8 92 друкує

len: 2147483647 java.lang.OutOfMemoryError: Requested array size exceeds VM limit
len: 2147483646 java.lang.OutOfMemoryError: Requested array size exceeds VM limit
len: 2147483645 OK
len: 2147483644 OK

Примітка: у Java 9 Strings використовуватиме байт [], що означатиме, що багатобайтові символи використовуватимуть більше одного байту та зменшують максимум далі. Якщо у вас є всі чотири байтові кодові точки, наприклад, емоджи, ви отримаєте лише близько 500 мільйонів символів


2
Компактні рядки в Java 9 використовують кодування Latin-1 або UTF-16. Немає кодування змінної довжини, тобто немає трьох байтових символів.
apangin

@apangin "Не мета використовувати альтернативні кодування, такі як UTF-8", дякую за виправлення.
Пітер Лорі

5

Чи розглядали ви BigDecimalзамість того, Stringщоб утримувати свої номери?


1
Це залежить від того, що програма буде робити з номерами. Якщо ви збираєтеся робити лише текстові речі, такі як пошук паліндромів, підрахунок (десяткових) цифр, то рядком краще. Якщо це буде робити арифметику, краще BigDecimal (або BigInteger).
Стівен C

Проблема полягає в тому, що "Для кожного К виведіть найменший паліндром, більший за K." (де K - вказане число). Вивести перший паліндром меншим за K. було б тривіально просто. Вам потрібно арифметику, щоб знайти один більший за K. Приклад: Знайдіть наступний паліндром більший за 999999999999 або наступний паліндром більший за 12922.
Thorbjørn Ravn Andersen

4

Integer.MAX_VALUE - це максимальний розмір рядка + залежить від розміру вашої пам’яті, але Проблема в Інтернет-судді сфери вам не потрібно використовувати ці функції


3

Java9 використовує байт [] для зберігання String.value, тому в Java9 ви можете отримати лише близько 1 ГБ рядків. З іншого боку, Java8 може мати 2 Гб.

Під символом я маю на увазі "char" s, деякий персонаж не є представницьким у BMP (як деякі емоджи), тому знадобиться більше (зараз 2) символів.


4
Чи можете ви додати посилання на обмеження розміру струни Java-9 до 1 ГБ від 2 Гб
Aditya Gupta,

-1

Купи частина погіршується, мої друзі. Гарантія, що UTF-16 не може бути обмежена 16 бітами і може розширюватися до 32


2
За винятком того, що charтип Java становить точно 16 біт, тому кількість біт, які використовує UTF-16, насправді не має значення ...
awksp
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.