
ç§ã¯è¶£å³ããããŸãïŒç§ã¯ã€ã³ã¿ãŒãããã§èŠã€ããJavaã®å
žåçãªã¿ã¹ã¯ã«å¯ŸããããŸããŸãªãœãªã¥ãŒã·ã§ã³ãåéãããµã€ãº/ããã©ãŒãã³ã¹/ãšã¬ã¬ã³ã¹ã§æãæé©ãªãã®ãéžæããããšããŸãã ãŸã第äžã«ãããã©ãŒãã³ã¹ã®é¢ã§ã Javaããã°ã©ãã³ã°ã§ããèŠããããMapã®ãã€ãã¹ãããè¡ã®åºçŸåæ°ãããŸããŸãªãœãªã¥ãŒã·ã§ã³ïŒãçŸããããªã©ïŒãšãã®ããã©ãŒãã³ã¹ã®ã«ãŠã³ããªã©ãäžè¬çãªã¿ã¹ã¯ãèŠãŠã¿ãŸãããã
è±èªçã¯Stackoverflowã«ãããŸãïŒ ãããããã€ãã¹ã ãéšåæååã®åºçŸãã«ãŠã³ã ããŸã ã
ãŸããããããæãæçšãªJavaã©ã€ãã©ãªãšãã¬ãŒã ã¯ãŒã¯ã®å
æ¬çãªã³ã¬ã¯ã·ã§ã³ã§ãããç§ã®ãªãŒãã³ãœãŒã¹ã®åœ¹ç«ã€java-linksãããžã§ã¯ããã芧ã«ãªãããšããå§ãããŸãã
äžè¬çãªç®æ¬¡ãããŒãã·ãŒãã 1.ããããã€ãã¹
ãããã£ãŠãã€ã³ã¿ãŒãããã§æ€çŽ¢ããå ŽåãããŒãšå€ãéèŠã§ããäžè¬çãªå Žåã«ããããã¢ãŒãå®è¡ããããŸããŸãªæ¹æ³ããããŸãïŒãã¡ãããããŒãŸãã¯å€ã ãããã€ãã¹ããããšã¯åºæ¬çã«è¡ãããŸãïŒã ãããã®ããã€ãã¯æ§æç³ã§ã®ã¿ç°ãªããããã€ãã¯æ ¹æ¬çã«ç°ãªããŸãã å®éããã¡ãããã©ã®ãœãªã¥ãŒã·ã§ã³ãé
ãããã©ã®ãœãªã¥ãŒã·ã§ã³ãéããã¯é·ãéç¥ãããŠããŸãããããã§ããªãŠã ã§ã©ãã ãåŸãããã®ããšæããŸãã
å®å
šãæãããã«ãéåžžã®Mapã®ãã€ãã¹ã ãã§ãªãã Apache Collections
IterableMapãšEclipse (CS) collections
MutableMapã®é¡äŒŒç©ãæ€èšããŠã¿ãŸãããã
ãªãã·ã§ã³ãèŠãŠã¿ãŸãããïŒ
åé¡ã®æ¡ä»¶ã¯ãæ°å€ã®ãããããããŸãããã®ãããã®ãã¹ãŠã®ããŒãšãã¹ãŠã®å€ã®åèšãæ¢ããŸãã ãã®ãããªã¿ã¹ã¯ã¯ãäžæ¹ã§ã¯åçŽåãããä»æ¹ã§ã¯ãJavaãªããã£ãã€ã¶ãŒãã³ãŒãã®äžéšãç Žæ£ã§ããªãããšãä¿èšŒããŸãã
iterator ã Map.Entryããã³whileã«ãŒãã䜿çšããŸãã æãçŸãããªãã·ã§ã³ã§ã¯ãªããå®éã«ã¯ãªãã·ã§ã³ïŒ2ïŒã®é¡äŒŒç©ã§ããããããã®éããèŠãŠã¿ãŸãããã
long i = 0; Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator(); while (it.hasNext()) { Map.Entry<Integer, Integer> pair = it.next(); i += pair.getKey() + pair.getValue(); }
Map.Entryãšforeachã«ãŒãã䜿çšããŸã ã ããããã€ãã¹ã®ã¯ã©ã·ãã¯ããŒãžã§ã³ã
long i = 0; for (Map.Entry<Integer, Integer> pair : map.entrySet()) { i += pair.getKey() + pair.getValue(); }
Java 8
ããforeachã䜿çšãJava 8
ã Java 8ã§ç»å Žããæ°ããã¡ãœããã®çç£æ§ãèŠãŠã¿ãŸãããã
final long[] i = {0}; map.forEach((k, v) -> i[0] += k + v);
keySetãšforeachã䜿çšããŸãã ãã®æ¹æ³ã¯éåžžã«é
ããšèããããŠãããåé¡ã¯ã©ãããããã§ãã
long i = 0; for (Integer key : map.keySet()) { i += key + map.get(key); }
keySetãšiteratorã䜿çšããŸã ã å®éããªãã·ã§ã³4ã«ã¯æ§æç³è¡£ã®ã¿ããããŸãã
long i = 0; Iterator<Integer> itr2 = map.keySet().iterator(); while (itr2.hasNext()) { Integer key = itr2.next(); i += key + map.get(key); }
forããã³Map.Entryã䜿çšã ãŸã ã ãå€ãã¹ã¿ã€ã«ãã®ã¿ã®ã¢ããã°1ããã³2
long i = 0; for (Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator(); entries.hasNext(); ) { Map.Entry<Integer, Integer> entry = entries.next(); i += entry.getKey() + entry.getValue(); }
Java 8
ãšStream Apiã®äœ¿çš
final long[] i = {0}; map.entrySet().stream().forEach(e -> i[0] += e.getKey() + e.getValue());
7aã mapToLongãšsumã§Java 8
ãšStream Apiã䜿çšãã
map.entrySetïŒïŒãstreamïŒïŒãmapToLongïŒe-> e.getKeyïŒïŒ+ e.getValueïŒïŒïŒãsumïŒïŒ;
Java 8
ãšParallel Stream Apiã®äœ¿çš
final long[] i = {0}; map.entrySet().stream().parallel().forEach(e -> i[0] += e.getKey() + e.getValue());
8aã mapToLongããã³sumã§Java 8
ããã³ãã©ã¬ã«ã¹ããªãŒã APIã䜿çšãã
map.entrySet().parallelStream().mapToLong(e -> e.getKey() + e.getValue()).sum();
Apache Collections
IterableMapã䜿çšãApache Collections
ã ãã®ãããã¯ãéåžžãšã¯ç°ãªãæ¹æ³ã§ç§»åããŸãã
long i = 0; MapIterator<Integer, Integer> it = iterableMap.mapIterator(); while (it.hasNext()) { i += it.next() + it.getValue(); }
Eclipse collections
ïŒä»¥åã®GSã³ã¬ã¯ã·ã§ã³ïŒããMutableMapã䜿çšããŸãã ãã®ãããã¯ãJava 8ãç»å Žãããããã¯ããã«æ©ãforEachã¡ãœãããååŸããŸããã
final long[] i = {0}; mutableMap.forEachKeyValue((key, value) -> { i[0] += key + value; });
æ§èœè©Šéš
å
žåçãªèŠå ïŒãã¹ãŠã®çµæã¯ãã®ãŸãŸã§ãããã©ãŒãã³ã¹æž¬å®ã¯è€éãªãã®ã§ããã·ã¹ãã ã§ã¯ãã¹ãŠã®æ°å€ãå®å
šã«ç°ãªãå Žåãããããã github'eã®ãœãŒã¹ã³ãŒããä¿¡ããŠã¯ãããŸãããåžžã«èªåã§çµæãååŸã§ããŸãã ããã©ãŒãã³ã¹ã枬å®ãããšãã«ç§ãã©ããã§ééãããšæããªãïŒãããŠããã¯åžžã«å¯èœã§ãïŒãå人çãªã¡ãã»ãŒãžãã³ã¡ã³ããæžããŠããã ããã°ãããããã§ãã
ã¢ãŒã=å¹³åæéïŒAverageTimeïŒãã·ã¹ãã = Win 8.1 64ããããIntel i7-4790 3.60GHz 3.60GHzã16 GBãã¹ã³ã¢ãäœãã»ã©è¯ãïŒ
1ïŒå°ããªãããïŒ100èŠçŽ ïŒã®å Žåãã¹ã³ã¢0.312ãæè¯ã®å€ã§ãã
Benchmark Size Mode Cnt Score Error Units 3. ForEachAndJava8 100 avgt 100 0.312 ± 0.003 us/op 10. EclipseMap 100 avgt 100 0.354 ± 0.003 us/op 2. ForEachAndMapEntry 100 avgt 100 0.403 ± 0.005 us/op 1. WhileAndMapEntry 100 avgt 100 0.427 ± 0.006 us/op 6. ForAndIterator 100 avgt 100 0.427 ± 0.006 us/op 7a Java8StreamApi2 100 avgt 100 0.509 ± 0.036 us/op 7. Java8StreamApi 100 avgt 100 0.529 ± 0.004 us/op 9. ApacheIterableMap 100 avgt 100 0.585 ± 0.008 us/op 4. KeySetAndForEach 100 avgt 100 0.937 ± 0.011 us/op 5. KeySetAndIterator 100 avgt 100 0.94 ± 0.011 us/op 8. Java8StreamApiParallel 100 avgt 100 6.066 ± 0.051 us/op 8a. Java8StreamApiparallel2 100 avgt 5 9.468 ± 0.333 us/op
2ïŒ10,000åã®èŠçŽ ãæã€äžèŠæš¡ãããã®å Žåãã¹ã³ã¢35.301ãæé©ãªå€ã§ã
Benchmark Size Mode Cnt Score Error Units 10. EclipseMap 10000 avgt 100 35.301 ± 0.697 us/op 3. ForEachAndJava8 10000 avgt 100 39.797 ± 0.309 us/op 2. ForEachAndMapEntry 10000 avgt 100 43.149 ± 0.313 us/op 1. WhileAndMapEntry 10000 avgt 100 43.295 ± 0.314 us/op 6. ForAndIterator 10000 avgt 100 44.009 ± 0.379 us/op 7. Java8StreamApi 10000 avgt 100 49.378 ± 0.415 us/op 5. KeySetAndIterator 10000 avgt 100 97.844 ± 0.896 us/op 4. KeySetAndForEach 10000 avgt 100 99.317 ± 0.862 us/op 8. Java8StreamApiParallel 10000 avgt 100 112.364 ± 0.167 us/op 9. ApacheIterableMap 10000 avgt 100 138.379 ± 1.387 us/op
3ïŒ30,000åã®èŠçŽ ãæã€ãããã®å Žåãã¹ã³ã¢122.277ãæé©ãªå€ã§ãã
Benchmark Size Mode Cnt Score Error Units 8a. Java8StreamApiparallel2 30000 avgt 100 95.444 ± 13.706 us/op 10. EclipseMap 30000 avgt 100 122.277 ± 3.896 us/op 3. ForEachAndJava8 30000 avgt 100 136.906 ± 2.392 us/op 2. ForEachAndMapEntry 30000 avgt 100 145.845 ± 1.895 us/op 1. WhileAndMapEntry 30000 avgt 100 149.186 ± 2.621 us/op 6. ForAndIterator 30000 avgt 100 149.353 ± 2.427 us/op 7a. Java8StreamApi2 30000 avgt 100 180.803 ± 53.062 us/op 7. Java8StreamApi 30000 avgt 100 181.114 ± 3.272 us/op 8. Java8StreamApiParallel 30000 avgt 100 342.546 ± 1.206 us/op 5. KeySetAndIterator 30000 avgt 100 350.564 ± 8.662 us/op 4. KeySetAndForEach 30000 avgt 100 364.362 ± 9.416 us/op 9. ApacheIterableMap 30000 avgt 100 536.749 ± 25.819 us/op
ã±ãŒã¹8aïŒmapToIntãšsumã䜿çšãã䞊åã¹ããªãŒã ïŒãæ°å€ããŒã¿ãåŠçããããã«æ£ç¢ºãªçµæã瀺ããŠããããšã«æ³šæããŠãã ãã;å®éã®åé¡ã§ã¯ãåžžã«é©çšã§ãããšã¯éããŸããã
ã°ã©ãïŒãããã®ãµã€ãºã«å¿ãããã¹ãïŒ

ããŒãã«ïŒããããµã€ãºã«å¿ãããã¹ãïŒ
Benchmark 100 500 900 1300 1700 2100 2500 10. EclipseMap 0.354 1.384 3.816 3.304 6.68 7.427 8.712 3. ForEachAndJava8 0.312 1.692 3.143 4.265 6.506 8.343 9.821 6. ForAndIterator 0.427 2.089 3.746 4.776 7.407 9.091 10.753 2. ForEachAndMapEntry 0.403 2.536 3.951 5.028 7.503 9.211 10.918 1. WhileAndMapEntry 0.427 2.026 3.4815 4.937 7.511 9.217 12.22 7. Java8StreamApi 0.529 2.343 4.264 5.399 8.826 12.633 12.918 9. ApacheIterableMap 0.585 2.725 5.574 9.292 13.01 17.719 23.882 5. KeySetAndIterator 0.94 4.592 8.24 12.496 16.077 21.012 24.389 4. KeySetAndForEach 0.937 4.572 8.251 12.522 14.831 20.502 24.881 8. Java8StreamApiParallel 6.066 12.152 16.563 18.512 25.987 28.813 33.336
GitHubã§ã®ãã¹ãŠã®ãã¹ã
èŠå ïŒHashMapãEclipseMapãApacheIterableMapã®ãã€ãã¹ã¯ãè¡çªãã»ãšãã©ãªãå
žåçãªå Žåã«ã®ã¿èæ
®ãããè¡çªãå€ãå Žåãçµæã¯å®å
šã«ç°ãªãå¯èœæ§ããããŸãã ãŸããèŠçŽ ã®è¿œå ãã©ã³ãã ã¢ã¯ã»ã¹ãªã©ã®ã±ãŒã¹ã¯èæ
®ãããŠããŸãããã€ãŸãããã®ãã¹ãã ãã§ã¯ãã©ã®ããããäžè¬ã«é«éã§åªããŠããããå€æããããšã¯ã§ããŸããã
2.æååå
ã®éšåæååã®åºçŸåæ°ãæ°ãã
ãããã£ãŠã次ã®ãµãã¹ããªã³ã°ãååŸãããã®äžã®ãã¹ãŠã®ãã€ã³ããèŠã€ããŸãã
String testString = "abcd";
ç§ã¯ããã«èŠåãããã£ãïŒãã¹ãã®ããã«StackOverflowãããã¯ã§ææ¡ããããã¹ãŠã®ãªãã·ã§ã³ãæ¡çšããŸãããåžžèã¯ãããã®ããã€ããç§ã®ãæ°ã«å
¥ãã®é¡åŸ®é¡ã§ã®æé©ãªéä»ãããã¯çšé ãããšã瀺åããŸãããç§ã¯ããããã®å Žåã«äœãèµ·ãããèå³ããããŸããã ãããã£ãŠã 以äžã®ãªãã·ã§ã³ã®ãã¹ãŠãå®éã®ã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšãããã¹ãã§ã¯ãªãããšã«æ³šæããŠãã ãã ïŒ
1ïŒ Apache Commonsã䜿çšãã
int apache = StringUtils.countMatches(testString, "."); System.out.println("apache = " + apache);
2ïŒ Spring Frameworkã®äœ¿çš
int spring = org.springframework.util.StringUtils.countOccurrencesOf(testString, "."); System.out.println("spring = " + spring);
3ïŒ çœ®æã®äœ¿çš
int replace = testString.length() - testString.replace(".", "").length(); System.out.println("replace = " + replace);
4ïŒ replaceAllã®äœ¿çšïŒã±ãŒã¹1ïŒ
int replaceAll = testString.replaceAll("[^.]", "").length(); System.out.println("replaceAll = " + replaceAll);
5ïŒ replaceAllã®äœ¿çšïŒã±ãŒã¹2ïŒ
int replaceAllCase2 = testString.length() - testString.replaceAll("\\.", "").length(); System.out.println("replaceAll (second case) = " + replaceAllCase2);
6ïŒ ã¹ããªããã䜿çšãã
int split = testString.split("\\.",-1).length-1; System.out.println("split = " + split);
7ïŒ Java8ã®äœ¿çšïŒã±ãŒã¹1ïŒã ä»ã®ãªãã·ã§ã³ãšã¯ç°ãªããéšåæååã§ã¯ãªãæåã®ã¿ãæ€çŽ¢ã§ããããšã«æ³šæããŠãã ãã ã
long java8 = testString.chars().filter(ch -> ch =='.').count(); System.out.println("java8 = " + java8);
8ïŒ Java8ã䜿çšãã ïŒã±ãŒã¹2ïŒãããããããŠãã³ãŒãæååã®å Žåãã±ãŒã¹1ãããå°ãè¯ãã§ããããä»ã®ãªãã·ã§ã³ãšã¯ç°ãªããéšåæååã§ã¯ãªãæåã®ã¿ãæ€çŽ¢ã§ããããšã«æ³šæããŠãã ãã ã
long java8Case2 = testString.codePoints().filter(ch -> ch =='.').count(); System.out.println("java8 (second case) = " + java8Case2);
9ïŒ StringTokenizerã®äœ¿çš
int stringTokenizer = new StringTokenizer(" " +testString + " ", ".").countTokens()-1; System.out.println("stringTokenizer = " + stringTokenizer);
åŸè
ã®ãªãã·ã§ã³ã¯ã2ã€ã®ãã€ã³ãã1ã€ãšèŠãªããããããa ... bc ... dãŸãã¯... abcdãŸãã¯a .... b ...... c ... ..d ...ããã€ãã®ãã€ã³ãã¯1ã€ãšèŠãªãããŸãã
å
žåçãªèŠå ïŒãã¹ãŠã®çµæã¯ãã®ãŸãŸã§ãããã©ãŒãã³ã¹æž¬å®ã¯è€éãªãã®ã§ããã·ã¹ãã ã§ã¯ãã¹ãŠã®æ°å€ãå®å
šã«ç°ãªãå Žåãããããã github'eã®ãœãŒã¹ã³ãŒããä¿¡ããŠã¯ãããŸãããåžžã«èªåã§çµæãååŸã§ããŸãã ããã©ãŒãã³ã¹ã枬å®ãããšãã«ç§ãã©ããã§ééãããšæããªãïŒãããŠããã¯åžžã«å¯èœã§ãïŒãå人çãªã¡ãã»ãŒãžãã³ã¡ã³ããæžããŠããã ããã°ãããããã§ãã
GitHubã§ã®ãã¹ãŠã®ãã¹ã
çãè¡ã§ã®æž¬å® ïŒ JMHã䜿çšãã¢ãŒã= AverageTimeã 0.010
0.351
ãããè¯ãïŒïŒ
Benchmark Mode Cnt Score Error Units 1. countMatches avgt 5 0.010 ± 0.001 us/op 2. countOccurrencesOf avgt 5 0.010 ± 0.001 us/op 3. stringTokenizer avgt 5 0.028 ± 0.002 us/op 4. java8_1 avgt 5 0.077 ± 0.005 us/op 5. java8_2 avgt 5 0.078 ± 0.003 us/op 6. split avgt 5 0.137 ± 0.009 us/op 7. replaceAll_2 avgt 5 0.302 ± 0.047 us/op 8. replace avgt 5 0.303 ± 0.034 us/op 9. replaceAll_1 avgt 5 0.351 ± 0.045 us/op
2142æåã®é·ãã®é·ãè¡ã§ã®æž¬å®çµæ ïŒ JMHã䜿çšãmode = AverageTimeã 0.010
å€ã¯0.351
ãããåªããŠããŸãïŒïŒ
Benchmark Mode Cnt Score Error Units 1. countMatches avgt 5 2.392 ± 0.172 us/op 2. countOccurrencesOf avgt 5 2.362 ± 0.060 us/op 3. stringTokenizer avgt 5 5.931 ± 0.112 us/op 4. java8 avgt 5 9.626 ± 0.463 us/op 5. java8_1 avgt 5 8.586 ± 0.251 us/op 6. split avgt 5 21.201 ± 1.037 us/op 7. replaceAll2 avgt 5 26.614 ± 1.026 us/op 8. replaceAll1 avgt 5 31.505 ± 1.046 us/op 9. replace avgt 5 33.462 ± 2.329 us/op
PSè±èªçã¯Stackoverflowã§èŠã€ããããšãã§ããŸãïŒ ãããããã€ãã¹ã ããµãã¹ããªã³ã°ã®åºçŸãã«ãŠã³ãã ãŸã ãç§ã®ãããžã§ã¯ãã®ãœãŒã¹ã³ãŒãã¯ã useful-java-linksã§ãã ããããªãããã®èšäºãæ°ã«å
¥ã£ãŠãããŠãããã«ãµãããããšæã£ãããSOãŸãã¯github'eã®ãã©ã¹ã«æè¬ããŸãã
PPSãŸããç§ã®ãªãŒãã³ãœãŒã¹ã®ã useful-java-linksããããžã§ã¯ãïŒããããæãæçšãªJavaã©ã€ãã©ãªããã¬ãŒã ã¯ãŒã¯ããã·ã¢èªã®æè²ãããªã®ã³ã¬ã¯ã·ã§ã³ïŒãã芧ã«ãªãããšããå§ãããŸãã ãã®ãããžã§ã¯ãã«ã¯åæ§ã®è±èªçãããã1ã€ã®Mavenãããžã§ã¯ãã§ããŸããŸãªJavaã©ã€ãã©ãªã®ç°¡åãªãµã³ãã«ã®ã³ã¬ã¯ã·ã§ã³ãæºåããããã«ããªãŒãã³ãœãŒã¹ã®Hello worldãµããããžã§ã¯ããéå§ããŠããŸãïŒãååã«æè¬ããŸãïŒã
äžè¬çãªç®æ¬¡ãããŒãã·ãŒãã