Combien de caractères une chaîne Java peut-elle avoir?

157

J'essaie le problème The Next Palindrome de Sphere Online Judge (SPOJ) où je dois trouver un palindrome pour un entier allant jusqu'à un million de chiffres. J'ai pensé à utiliser les fonctions de Java pour inverser les chaînes, mais permettraient-elles à une chaîne d'être aussi longue?

andandandand
la source
êtes-vous en train de dire que vous devez écrire une fonction qui génère des palindromes, dont la taille est spécifiée par l'utilisateur et peut contenir jusqu'à 1 million de caractères?
Robert
3
Le problème (de SPOJ) peut contenir un fichier de 100 Go, et vous aimez le charger dans une chaîne à la fois? Sérieusement ... veuillez utiliser un scanner!
Grim
Possibilité de duplication de la longueur maximale
Bergi

Réponses:

242

Vous devriez pouvoir obtenir une chaîne de longueur

  1. Integer.MAX_VALUEtoujours 2,147,483,647 (2 31 - 1)
    (Défini par la spécification Java, la taille maximale d'un tableau, que la classe String utilise pour le stockage interne)
    OU

  2. Half your maximum heap size(puisque chaque caractère est de deux octets) selon la valeur la plus petite .

Bill le lézard
la source
43
... ou votre taille de tas maximale divisée par 2 ... puisque le caractère est de 2 octets
ChssPly76
2
@ ChssPly76: Oui, c'est exact. J'ai édité ma réponse, merci.
Bill the Lizard
2
comment connaître la taille maximale du tas? De plus, je ne sais pas quelle machine virtuelle Java le juge utilise pour tester mon problème. Integer.MAX_VALUE fait-il partie de la spécification de la JVM dépendante?
andandandand
6
Integer.MAX_VALUE est toujours 2147483647 (2 ^ 31 - 1), cela fait partie de la spécification Java.
cd1
4
En supposant une JVM 64 bits, car vous auriez besoin de 8 Go de mémoire virtuelle pour stocker une chaîne de cette longueur.
Robert Fraser
21

Je crois qu'ils peuvent contenir jusqu'à 2 ^ 31-1 caractères, car ils sont détenus par un tableau interne et les tableaux sont indexés par des entiers en Java.

aperkins
la source
L'implémentation interne n'est pas pertinente - il n'y a aucune raison pour que les données de caractères ne puissent pas être stockées dans un tableau de longs, par exemple. Le problème est que l'interface utilise des ints pour la longueur. getByteset similaires peuvent avoir des problèmes si vous essayez une très grande chaîne.
Tom Hawtin - tackline
C'est vrai - j'impliquais ce fait. Ma faute.
aperkins
15

Alors que vous pouvez en théorie des caractères Integer.MAX_VALUE, la JVM est limitée dans la taille du tableau qu'elle peut utiliser.

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);
        }
    }
}

sur les impressions de la mise à jour 92 d'Oracle Java 8

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

Remarque: dans Java 9, les chaînes utiliseront l'octet [], ce qui signifie que les caractères multi-octets utiliseront plus d'un octet et réduiront encore le maximum. Si vous avez les quatre points de code octets, par exemple les emojis, vous n'obtiendrez qu'environ 500 millions de caractères

Peter Lawrey
la source
2
Les chaînes compactes dans Java 9 utilisent le codage Latin-1 ou UTF-16. Pas de codage de longueur variable, c'est-à-dire pas de caractères à trois octets.
apangin
@apangin "Ce n'est pas un but d'utiliser des encodages alternatifs comme UTF-8" merci pour la correction.
Peter Lawrey
5

Avez-vous envisagé d'utiliser BigDecimalau lieu de Stringconserver vos numéros?

Thorbjørn Ravn Andersen
la source
1
Cela dépend de ce que l'application va faire avec les chiffres. S'il doit simplement faire des choses textuelles comme trouver des palindromes, compter des chiffres (décimaux), alors une chaîne est meilleure. S'il doit faire de l'arithmétique, un BigDecimal (ou BigInteger) est préférable.
Stephen C
Le problème est "Pour chaque K, produisez le plus petit palindrome supérieur à K." (où K est le nombre donné). Il serait trivialement simple de produire le premier palindrome plus petit que K. Vous avez besoin d'arithmétique pour en trouver un plus grand que K. Exemple: Trouvez le prochain palindrome plus grand que 999999999999, ou le prochain palindrome plus grand que 12922.
Thorbjørn Ravn Andersen
4

Integer.MAX_VALUE est la taille maximale de la chaîne + dépend de la taille de votre mémoire, mais le problème sur la sphère juge en ligne que vous n'avez pas à utiliser ces fonctions

Mite Mitreski
la source
3

Java9 utilise byte [] pour stocker String.value, vous ne pouvez donc obtenir qu'environ 1 Go de chaînes dans Java9. Java8, par contre, peut avoir des chaînes de 2 Go.

Par caractère, je veux dire "char", certains caractères ne sont pas représentables dans BMP (comme certains des emojis), donc cela prendra plus (actuellement 2) caractères.

Revin
la source
4
Pourriez-vous joindre une référence pour Java-9 limitant la taille de la chaîne à 1 Go à partir de 2 Go
Aditya Gupta
-1

La partie du tas empire, mes amis. UTF-16 n'est pas garanti pour être limité à 16 bits et peut s'étendre à 32

Joe Plante
la source
2
Sauf que le chartype de Java est exactement 16 bits, donc le nombre de bits utilisé par UTF-16 n'a pas vraiment d'importance ...
awksp