Question

Je viens d'apprendre la classe de scanner de Java et maintenant je me demande comment il se compare / rivalise avec le stringTokenizer et String.split. Je sais que StringTokenizer et String.split ne fonctionnent que sur les chaînes, alors pourquoi voudrais-je utiliser le scanner pour une chaîne? Le scanner est-il simplement destiné à être à guichet unique pour la séparation?

Était-ce utile?

La solution

Ce sont essentiellement des chevaux pour des cours.

  • Scanner est conçu pour les cas où vous devez analyser une chaîne, en retirant les 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 éventail de chaînes délimitées par une expression particulière.
  • String.split() et Pattern.split() Donnez-vous une syntaxe facile pour faire ce dernier, mais c'est essentiellement tout ce qu'ils font. Si vous souhaitez analyser les chaînes résultantes ou modifier le délimiteur à mi-chemin en fonction d'un jeton particulier, ils ne vous aideront pas avec cela.
  • StringTokenizer est encore plus restrictif que String.split(), et aussi un peu plus fidèle à utiliser. Il est essentiellement conçu pour retirer les jetons délimités par des sous-chaînes fixes. En raison de cette restriction, c'est environ deux fois plus vite que String.split(). (Voir mon comparaison de String.split() et StringTokenizer.) Il est également antérieur à l'API d'expressions régulières, dont String.split() fait partie.

Vous remarquerez de mes horaires que String.split() peut encore tokenize des milliers de cordes en quelques millisecondes sur une machine typique. De plus, il a l'avantage sur StringTokenizer qu'il vous donne la sortie en tant que tableau de chaîne, ce qui est généralement ce que vous voulez. En utilisant un Enumeration, tel que fourni par StringTokenizer, est trop "difficile syntaxiquement" la plupart du temps. De ce point de vue, StringTokenizer est un peu un gaspillage d'espace de nos jours, et vous pouvez aussi bien utiliser String.split().

Autres conseils

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

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

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

Pour une chose, split() Renvoie simplement un tableau, ce qui facilite l'utilisation d'une boucle foreach:

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

Scanner est construit plus comme un flux:

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

ou

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

(Il a un plutôt grande API, alors ne pensez pas que cela est toujours limité à des choses aussi simples.)

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

Personnellement, la seule fois où je me souvienne d'utiliser Scanner IS pour les projets scolaires, lorsque j'ai dû obtenir la contribution des utilisateurs de la ligne de commande. Cela facilite ce type d'opération. Mais si j'ai un String que je veux me séparer, c'est presque une évidence pour aller avec split().

StringTokenizer était toujours là. C'est le plus rapide de tous, mais l'idiome semblable à un énumération peut ne pas sembler aussi élégant que les autres.

Split est venu à l'existence sur JDK 1.4. Plus lent que Tokenizer mais plus facile à utiliser, car il est appelant à partir de la classe String.

Le scanner est venu sur JDK 1.5. Il est le plus flexible et comble un écart de longue date sur l'API Java pour soutenir un équivalent de la célèbre famille de fonctions CS Scanf.

La fente est lente, mais pas aussi lente que le scanner. StringTokenizer est plus rapide que Split. Cependant, j'ai trouvé que je pouvais obtenir le double de la vitesse, en échangeant une certaine flexibilité, pour obtenir un boost de vitesse, ce que j'ai fait chez JfastParser https://github.com/hughperkins/jfastparser

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

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

Si vous avez un objet String, vous souhaitez tokensize, favorisez l'utilisation de la chaîne diviser Méthode sur un stringTokenizer. Si vous analysez les données de texte d'une source à l'extérieur de votre programme, comme à partir d'un fichier ou de l'utilisateur, c'est là qu'un scanner est utile.

String.split semble être beaucoup plus lent que StringTokenizer. Le seul avantage avec Split est que vous obtenez un tableau de jetons. Vous pouvez également utiliser toutes les expressions régulières dans Split. org.apache.commons.lang.stringutils a une méthode divisée qui fonctionne beaucoup plus plus rapidement que n'importe lequel de deux à savoir. StringTokenizer ou String.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 intensive au processeur, ce que je ne suis toujours pas en mesure de trouver.

J'ai récemment fait quelques expériences sur les mauvaises performances de String.Split () dans des situations de performance sensibles aux performances. Vous pouvez trouver cela utile.

http://eblog.chrononsystems.com/hidden-evils-of-javas-stringsplit-and-stringr

L'essentiel est que String.Split () compile un modèle d'expression régulière à chaque fois et peut ainsi ralentir votre programme, par rapport à si vous utilisez un objet de motif précompilé et l'utilisez directement pour fonctionner sur une chaîne.

Pour les scénarios par défaut, je suggérerais également Pattern.Split (), mais si vous avez besoin de performances maximales (en particulier sur Android, toutes les solutions que j'ai testées sont assez lentes) et que vous n'avez qu'à vous séparer par un seul char, j'utilise maintenant ma propre méthode:

public static ArrayList<String> splitBySingleChar(final char[] s,
        final char splitChar) {
    final ArrayList<String> result = new ArrayList<String>();
    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 String(s, offset, count));
            }
            offset = i + 1;
            count = 0;
        } else {
            count++;
        }
    }
    if (count > 0) {
        result.add(new String(s, offset, count));
    }
    return result;
}

Utilisez "ABC" .toCharArray () pour obtenir le tableau char pour une chaîne. Par exemple:

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

Une différence importante est que String.Split () et Scanner peuvent produire des chaînes vides mais StringTokenizer ne le fait jamais.

Par exemple:

String str = "ab cd  ef";

StringTokenizer st = new StringTokenizer(str, " ");
for (int i = 0; st.hasMoreTokens(); i++) System.out.println("#" + i + ": " + st.nextToken());

String[] 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());

Production:

//StringTokenizer
#0: ab
#1: cd
#2: ef
//String.split()
#0: ab
#1: cd
#2: 
#3: ef
//Scanner
#0: ab
#1: cd
#2: 
#3: ef

En effet Nous pouvons remplacer le délimiteur "" par "+" dans l'exemple ci-dessus pour les faire se comporter comme StringTokenizer.

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

ABC | IJK

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top