Il y a deux méthodes:
private static void normalSplit(Ssortingng base){ base.split("\\."); } private static final Pattern p = Pattern.comstack("\\."); private static void patternSplit(Ssortingng base){ //use the static field above p.split(base); }
Et je les teste comme ceci dans la méthode principale:
public static void main(Ssortingng[] args) throws Exception{ long start = System.currentTimeMillis(); Ssortingng longstr = "abcdefghij";//use any long ssortingng you like for(int i=0;i<300000;i++){ normalSplit(longstr);//switch to patternSplit to see the difference } System.out.println((System.currentTimeMillis()-start)/1000.0); }
Intuitivement, je pense que Ssortingng.split
appellera finalement Pattern.comstack.split
(après beaucoup de travail supplémentaire) pour faire la vraie chose. Je peux construire l’object Pattern à l’avance (il est thread-safe) et accélérer la division.
Mais le fait est que l’utilisation du motif pré-construit est beaucoup plus lente que d’appeler directement Ssortingng.split
. J’ai essayé d’utiliser une chaîne de 50 caractères (avec MyEclipse). L’appel direct ne consum que la moitié du temps nécessaire pour utiliser un object Pattern pré-construit.
S’il vous plaît quelqu’un peut-il me dire pourquoi cela se produit?
Cela peut dépendre de l’implémentation réelle de Java. J’utilise OpenJDK 7, et ici, Ssortingng.split
effectivement Pattern.comstack(regex).split(this, limit)
, mais uniquement si la chaîne à scinder, regex
, est plus qu’un seul caractère.
Voir ici pour le code source, ligne 2312.
public Ssortingng[] split(Ssortingng regex, int limit) { /* fastpath if the regex is a (1)one-char Ssortingng and this character is not one of the RegEx's meta characters ".$|()[{^?*+\\", or (2)two-char Ssortingng and the first char is the backslash and the second is not the ascii digit or ascii letter. */ char ch = 0; if (((regex.count == 1 && // a bunch of other checks and lots of low-level code return list.subList(0, resultSize).toArray(result); } return Pattern.comstack(regex).split(this, limit); }
Comme vous vous séparez par "\\."
, il utilise le “raccourci”. C’est-à-dire si vous utilisez OpenJDK.
Voici le changement de comportement de Ssortingng.split
, effectué dans Java 7
. Voici ce que nous avons dans 7u40
:
public Ssortingng[] split(Ssortingng regex, int limit) { /* fastpath if the regex is a (1)one-char Ssortingng and this character is not one of the RegEx's meta characters ".$|()[{^?*+\\", or (2)two-char Ssortingng and the first char is the backslash and the second is not the ascii digit or ascii letter. */ char ch = 0; if (((regex.value.length == 1 && ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) || (regex.length() == 2 && regex.charAt(0) == '\\' && (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 && ((ch-'a')|('z'-ch)) < 0 && ((ch-'A')|('Z'-ch)) < 0)) && (ch < Character.MIN_HIGH_SURROGATE || ch > Character.MAX_LOW_SURROGATE)) { //do stuff return list.subList(0, resultSize).toArray(result); } return Pattern.comstack(regex).split(this, limit); }
Et c’est ce que nous avions en 6-b14
public Ssortingng[] split(Ssortingng regex, int limit) { return Pattern.comstack(regex).split(this, limit); }
Je pense que cela ne peut être expliqué que par l’optimisation JIT, Ssortingng.split en interne est implémenté comme suit:
Pattern.comstack(regex).split(this, limit);
et ça marche plus vite quand on est dans Ssortingng.class, mais quand j’utilise le même code dans le test:
for (int i = 0; i < 300000; i++) { //base.split("\\.");// switch to patternSplit to see the difference //p.split(base); Pattern.compile("\\.").split(base, 0); }
p.split(base)
le même résultat que p.split(base)