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

157

Я пытаюсь решить проблему следующего палиндрома из Sphere Online Judge (SPOJ), где мне нужно найти палиндром с целым числом до миллиона цифр. Я думал об использовании функций Java для реверсирования строк, но позволят ли они, чтобы строка была такой длинной?

andandandand
источник
Вы говорите, что вам нужно написать функцию, которая генерирует палиндромы, размер которых определяется пользователем и может быть длиной до 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.

aperkins
источник
Внутренняя реализация не имеет значения - нет причины, по которой, например, символьные данные не могут быть сохранены в массиве long. Проблема в том, что интерфейс использует целочисленные значения длины. getBytesи подобное может иметь проблемы, если вы попытаетесь использовать очень большую строку.
Том Хотин - Tackline
Это правда - я имел в виду этот факт. Виноват.
Аперкинс
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 будет использовать byte [], что будет означать, что многобайтовые символы будут использовать более одного байта и дополнительно уменьшать максимум. Если у вас есть все четыре байтовых кода, например, эмодзи, вы получите только около 500 миллионов символов

Питер Лори
источник
2
Компактные строки в Java 9 используют кодировку Latin-1 или UTF-16. Нет кодирования переменной длины, то есть нет трехбайтовых символов.
Апангин
@apangin "Не стоит использовать альтернативные кодировки, такие как UTF-8", спасибо за исправление.
Питер Лори
5

Рассматривали ли вы использовать BigDecimalвместо того, Stringчтобы держать свои номера?

Турбьерн Равн Андерсен
источник
1
Это зависит от того, что приложение собирается делать с числами. Если он собирается просто выполнять текстовые операции, такие как поиск палиндромов, подсчет (десятичных) цифр, тогда строка лучше. Если это будет делать арифметику, лучше использовать BigDecimal (или BigInteger).
Стивен С
Проблема в том, что «Для каждого K выведите наименьший палиндром больше, чем K.» (где K - заданное число). Было бы тривиально просто вывести первый палиндром, меньший, чем K. Вам понадобится арифметика, чтобы найти один, больший, чем K. Пример: найдите следующий палиндром, больший, чем 999999999999, или следующий палиндром, превышающий 12922.
Thorbjørn Ravn Andersen
4

Integer.MAX_VALUE - это максимальный размер строки + зависит от объема вашей памяти, но проблема в сфере онлайн судить, вам не нужно использовать эти функции

Клещ Митрески
источник
3

Java9 использует byte [] для хранения String.value, поэтому вы можете получить только около 1 Гб строк в Java9. Java8, с другой стороны, может иметь строки 2 ГБ.

Под символом я подразумеваю «символы», некоторые символы не могут быть представлены в BMP (например, некоторые смайлики), поэтому потребуется больше (в настоящее время 2) символов.

Ревин
источник
4
Не могли бы вы приложить ссылку на ограничение размера строки Java-9 до 1 ГБ с 2 ГБ
Адитья Гупта
-1

Куча часть становится хуже, друзья мои. UTF-16 не может быть ограничен 16 битами и может расширяться до 32

Джо Планте
источник
2
За исключением того, что charтип Java точно равен 16 битам, поэтому количество битов, используемых UTF-16, не имеет значения ...
awksp