Pourquoi dans Java 8 split parfois supprime les cordes à vide au début de la matrice de résultats?
Avant Java 8 lorsque nous nous sommes séparés sur la chaîne vide comme
String[] tokens = "abc".split("");
split mécanisme permettrait de diviser dans des lieux marqués avec |
|a|b|c|
parce que l'espace vide ""
existe avant et après chaque caractère. Donc, comme résultat qu'il pourrait générer, au premier abord, ce tableau
["", "a", "b", "c", ""]
et plus tard sera supprimer la fuite des chaînes vides (parce que nous n'avons pas explicitement négative de la valeur à limit
argument) de sorte qu'il sera enfin de retour
["", "a", "b", "c"]
Dans Java 8 split mécanisme semble avoir changé. Maintenant, quand nous utilisons
"abc".split("")
nous aurons ["a", "b", "c"]
tableau au lieu de ["", "a", "b", "c"]
donc, il semble que les cordes à vide au démarrage sont également supprimés. Mais cette théorie ne parvient pas parce que par exemple
"abc".split("a")
retourne un tableau avec une chaîne vide au début ["", "bc"]
.
Quelqu'un peut m'expliquer ce qui se passe ici et la façon dont les règles de split pour ce cas ont changé en Java8?
s.split("(?!^)")
semble fonctionner.Le comportement décrit dans ma question n'est pas un bug de pré Java-8 versions. Ce comportement n'était pas particulièrement très utile, mais il était encore correct (comme indiqué dans ma question), donc on ne peut pas dire qu'elle est "fixe". Je le vois plus comme une amélioration que nous pourrions utiliser
split("")
au lieu de cryptic (pour les personnes qui n'utilisent pas les regex) split("(?!^)")
ou split("(?<!^)")
ou quelques autres regexes.Rencontré le même problème après mise à jour de fedora Fedora 21, fedora 21 est livré avec le JDK 1.8, et mon IRC application de jeu est brisé à cause de cela.
Cette question semble être la seule de la documentation de cette modification de rupture dans Java 8. Oracle gauche de leurs liste des incompatibilités.
Ce changement dans le JDK juste m'a coûté 2 heures de traque de ce qui est mal. Le code fonctionne très bien sur mon ordinateur (JDK8) mais échoue mystérieusement sur une autre machine (JDK7). Oracle DEVRAIT VRAIMENT mise à jour de la documentation de String.split(String regex), plutôt que dans le Modèle.split ou Chaîne.split(String regex, int limite) car c'est de loin le plus courant d'utilisation. Java est connu pour sa portabilité aka soi-disant WORA. C'est un grand arrière-modification de rupture et de ne pas bien documenté.
OriginalL'auteur Pshemo | 2014-03-28
Vous devez vous connecter pour publier un commentaire.
Le comportement de
String.split
(qui appellePattern.split
) les changements entre Java 7 et Java 8.Documentation
La comparaison entre les documents de
Pattern.split
dans Java 7 et Java 8, nous observons la clause suivante est ajoutée:La même clause est également ajouté à
String.split
dans Java 8, par rapport à Java 7.L'implémentation de référence de
Laissez-nous comparer le code de
Pattern.split
de la référence de mise en œuvre en Java 7 et Java 8. Le code est extrait de grepcode, pour la version 7u40-b43 et 8-b132.Java 7
Java 8
L'ajout du code en Java 8 exclut la longueur nulle match au début de la chaîne d'entrée, ce qui explique le comportement ci-dessus.
Maintenir la compatibilité de
Problème suivant dans Java 8 et ci-dessus
De faire
split
se comporte de manière uniforme entre les versions et compatible avec le comportement en Java 8:(?!\A)
à la fin de la regex et enveloppez-la d'origine regex dans la non-capture d'un groupe(?:...)
(si nécessaire).(?!\A)
vérifie que la chaîne n'a pas de fin au début de la chaîne, ce qui implique que le match est vide match au début de la chaîne.Problème suivant dans Java 7 et avant
Il n'y a pas de solution générale pour faire
split
vers l'arrière-compatible avec Java 7 et avant, court de remplacement de tous instance desplit
pour pointer vers votre propre mise en œuvre.split("")
code de façon homogène à travers les différentes versions de java?Il est possible de le rendre compatible (suivre le comportement de Java 8) par l'ajout de
(?!^)
de les de la regex et enveloppez-la d'origine regex dans la non-capture d'un groupe(?:...)
(si nécessaire), mais je ne peux pas penser à un moyen de le rendre compatible en amont (suivre l'ancien comportement en Java 7 et avant).Merci pour l'explication. Pourriez-vous décrire
"(?!^)"
? Dans ce cas, il sera différent de""
? (Je suis très mauvais avec les regex! :-/).Son sens est affecté par
Pattern.MULTILINE
drapeau, tandis que\A
correspond toujours au début de la chaîne, indépendamment de drapeaux.OriginalL'auteur nhahtdh
Cela a été spécifié dans la documentation de
split(String regex, limite)
.Dans
"abc".split("")
vous avez obtenu un zéro-largeur match au début donc, le premier vide sous-chaîne n'est pas inclus dans le tableau résultant.Mais que, dans un deuxième extrait de quand vous divisez sur
"a"
vous avez obtenu une largeur positive de match (1 dans ce cas), de sorte que le vide leader de la sous-chaîne est incluse comme prévu.(Retiré hors de propos de code source)
Pour être juste je ne sais pas mais je suppose que c'est ok, puisque vous pouvez télécharger le JDK, et décompressez le fichier src qui contient toutes les sources. Donc, techniquement, tout le monde peut voir la source.
Le "open" en "open source" ne tenir pour quelque chose.
tout simplement parce que tout le monde peut le voir, vous ne pouvez pas re-publier
Vargas, IANAL, mais dans de nombreuses autres occasions de ce type d'un poste relève de la citation ou de l'utilisation juste de la situation. Plus sur le sujet est ici: meta.stackexchange.com/questions/12527/...
OriginalL'auteur Alexis C.
Il y avait un léger changement dans les docs pour
split()
à partir de Java 7 de Java 8. Plus précisément, la déclaration suivante a été ajoutée:(l'emphase est mienne)
La chaîne vide split génère une largeur nulle match au début, alors une chaîne vide n'est pas incluse au début du tableau qui en résulte, conformément à ce qui est spécifié ci-dessus. En revanche, votre deuxième exemple qui se divise sur
"a"
génère un positif-largeur match au début de la chaîne, alors une chaîne vide est en fait incluse au début de la matrice résultante.en fait, ici arshajii posté réponse quelques secondes avant de ZouZou, mais malheureusement ZouZou répondu à ma question plus tôt here. Je me demandais si je pose cette question car je connaissais déjà la réponse, mais il me semblait intéressant et ZouZou mérité quelques réputation pour ses précédentes observations.
Malgré le nouveau comportement ressemble plus à l' logique, c'est évidemment une compatibilité descendante pause. La seule justification de ce changement est que
"some-string".split("")
est assez rare cas..split("")
n'est pas la seule façon de split sans correspondance quoi que ce soit. Nous avons utilisé une anticipation positif regex dans jdk7 qui correspond aussi au début et a produit un vide à la tête de l'élément qui a maintenant disparu. github.com/spray/spray/commit/...OriginalL'auteur arshajii