Scanner vs. SsortingngTokenizer vs. Ssortingng.Split

Je viens d’apprendre la classe Scanner de Java et je me demande maintenant comment elle se compare / rivalise avec SsortingngTokenizer et Ssortingng.Split. Je sais que SsortingngTokenizer et Ssortingng.Split ne fonctionnent que sur les chaînes, alors pourquoi voudrais-je utiliser le scanner pour une chaîne? Le scanner est-il juste conçu pour être un guichet unique pour la séparation?

Ils sont essentiellement des chevaux pour les cours.

  • Scanner est conçu pour les cas où vous devez parsingr une chaîne, en extrayant des données de différents types. C’est très flexible, mais sans doute ne vous donne pas l’API la plus simple pour obtenir simplement un tableau de chaînes délimité par une expression particulière.
  • Ssortingng.split() et Pattern.split() vous donnent une syntaxe simple pour faire ce dernier, mais c’est essentiellement tout ce qu’ils font. Si vous souhaitez parsingr les chaînes résultantes ou modifier le délimiteur à mi-chemin en fonction d’un jeton particulier, elles ne vous aideront pas.
  • SsortingngTokenizer est encore plus ressortingctif que Ssortingng.split() , et un peu plus compliqué à utiliser. Il est essentiellement conçu pour extraire des jetons délimités par des sous-chaînes fixes. A cause de cette ressortingction, il est environ deux fois plus rapide que Ssortingng.split() . (Voir ma comparaison de Ssortingng.split() et SsortingngTokenizer .) Elle est également antérieure à l’API des expressions régulières, dont Ssortingng.split() fait partie.

Vous remarquerez à partir de mes timings que Ssortingng.split() peut encore numériser des milliers de chaînes en quelques millisecondes sur une machine classique. En outre, il a l’avantage par rapport à SsortingngTokenizer qu’il vous donne le résultat sous la forme d’un tableau de chaînes, ce qui est généralement ce que vous voulez. L’utilisation d’une Enumeration , telle que fournie par SsortingngTokenizer , est la plupart du temps “syntaxiquement délicate”. De ce sharepoint vue, SsortingngTokenizer est un peu un gaspillage d’espace de nos jours, et vous pouvez aussi bien utiliser Ssortingng.split() .

Commençons par éliminer SsortingngTokenizer . Il vieillit et ne supporte même pas les expressions régulières. Sa documentation indique:

SsortingngTokenizer est une classe héritée qui est conservée pour des raisons de compatibilité, bien que son utilisation soit déconseillée dans le nouveau code. Il est recommandé que toute personne recherchant cette fonctionnalité utilise la méthode split de Ssortingng ou le package java.util.regex place.

Alors jetons-le tout de suite. Cela laisse split() et Scanner . Quelle est la différence entre eux?

D’une part, split() renvoie simplement un tableau, ce qui facilite l’utilisation d’une boucle foreach:

 for (Ssortingng token : input.split("\\s+") { ... } 

Scanner se construit plus comme un stream:

 while (myScanner.hasNext()) { Ssortingng token = myScanner.next(); ... } 

ou

 while (myScanner.hasNextDouble()) { double token = myScanner.nextDouble(); ... } 

(Il a une API assez grande , alors ne pensez pas que cela se limite toujours à des choses aussi simples.)

Cette interface de style stream peut être utile pour parsingr des fichiers texte simples ou des entrées de console, lorsque vous n’avez pas (ou ne pouvez pas obtenir) toutes les entrées avant de commencer à parsingr.

Personnellement, le seul moment où je me souviens de l’utilisation de Scanner concerne les projets scolaires, alors que je devais recevoir des entrées utilisateur depuis la ligne de commande. Cela facilite ce genre d’opération. Mais si j’ai une Ssortingng que je veux diviser, c’est presque une évidence de partir avec split() .

SsortingngTokenizer était toujours là. C’est le plus rapide de tous, mais l’idiome semblable à l’énumération pourrait ne pas être aussi élégant que les autres.

le split est né sur JDK 1.4. Plus lent que le tokenizer mais plus facile à utiliser, car il est appelable à partir de la classe Ssortingng.

Le scanner est arrivé sur JDK 1.5. Il est le plus flexible et comble une lacune de longue date sur l’API Java pour prendre en charge un équivalent de la célèbre famille de fonctions Cs scanf.

Split est lent, mais pas aussi lent que Scanner. SsortingngTokenizer est plus rapide que split. Cependant, j’ai trouvé que je pouvais obtenir le double de vitesse, en échangeant une certaine flexibilité, pour obtenir une accélération de la vitesse, ce que j’ai fait à JFastParser https://github.com/hughperkins/jfastparser

Test sur une chaîne contenant un million de doubles:

 Scanner: 10642 ms Split: 715 ms SsortingngTokenizer: 544ms JFastParser: 290ms 

Si vous souhaitez numériser un object Ssortingng, privilégiez l’utilisation de la méthode split de Ssortingng sur un SsortingngTokenizer. Si vous parsingz des données textuelles provenant d’une source extérieure à votre programme, par exemple à partir d’un fichier ou de l’utilisateur, c’est là qu’un scanner est utile.

Ssortingng.split semble être beaucoup plus lent que SsortingngTokenizer. Le seul avantage de la division est que vous obtenez un tableau des jetons. Vous pouvez également utiliser toutes les expressions régulières dans split. org.apache.commons.lang.SsortingngUtils a une méthode de partage qui fonctionne beaucoup plus rapidement que n’importe lequel des deux. SsortingngTokenizer ou Ssortingng.split. Mais l’utilisation du processeur pour tous les trois est presque la même. Nous avons donc également besoin d’une méthode moins gourmande en ressources CPU, que je n’arrive toujours pas à trouver.

J’ai récemment fait des expériences sur les mauvaises performances de Ssortingng.split () dans des situations très sensibles aux performances. Vous pouvez trouver cela utile.

http://eblog.chrononsystems.com/hidden-evils-of-javas-ssortingngsplit-and-ssortingngr

L’essentiel est que Ssortingng.split () comstack un modèle d’expression régulière à chaque fois et peut donc ralentir votre programme, par rapport à si vous utilisez un object Pattern précompilé et l’utiliser directement pour opérer sur une chaîne.

Pour les scénarios par défaut, je suggérerais aussi Pattern.split () mais si vous avez besoin de performances maximales (en particulier sur Android, toutes les solutions testées sont assez lentes) et que vous devez uniquement les diviser, j’utilise ma propre méthode:

 public static ArrayList splitBySingleChar(final char[] s, final char splitChar) { final ArrayList result = new ArrayList(); final int length = s.length; int offset = 0; int count = 0; for (int i = 0; i < length; i++) { if (s[i] == splitChar) { if (count > 0) { result.add(new Ssortingng(s, offset, count)); } offset = i + 1; count = 0; } else { count++; } } if (count > 0) { result.add(new Ssortingng(s, offset, count)); } return result; } 

Utilisez “abc” .toCharArray () pour obtenir le tableau de caractères pour une chaîne. Par exemple:

 Ssortingng s = " a bb ccc dddd eeeee ffffff ggggggg "; ArrayList result = splitBySingleChar(s.toCharArray(), ' '); 

Une différence importante est que Ssortingng.split () et Scanner peuvent produire des chaînes vides, mais SsortingngTokenizer ne le fait jamais.

Par exemple:

 Ssortingng str = "ab cd ef"; SsortingngTokenizer st = new SsortingngTokenizer(str, " "); for (int i = 0; st.hasMoreTokens(); i++) System.out.println("#" + i + ": " + st.nextToken()); Ssortingng[] split = str.split(" "); for (int i = 0; i < split.length; i++) System.out.println("#" + i + ": " + split[i]); Scanner sc = new Scanner(str).useDelimiter(" "); for (int i = 0; sc.hasNext(); i++) System.out.println("#" + i + ": " + sc.next()); 

Sortie:

 //SsortingngTokenizer #0: ab #1: cd #2: ef //Ssortingng.split() #0: ab #1: cd #2: #3: ef //Scanner #0: ab #1: cd #2: #3: ef 

Cela est dû au fait que le délimiteur de Ssortingng.split () et Scanner.useDelimiter () n'est pas simplement une chaîne, mais une expression régulière. Nous pouvons remplacer le délimiteur "" par "+" dans l'exemple ci-dessus pour les faire se comporter comme SsortingngTokenizer.

Ssortingng.split () fonctionne très bien mais a ses propres limites, comme si vous vouliez diviser une chaîne comme indiqué ci-dessous en fonction d’un symbole simple ou double (|), cela ne fonctionne pas. Dans cette situation, vous pouvez utiliser SsortingngTokenizer.

ABC | IJK