diff --git a/test/micro/org/openjdk/bench/java/util/stream/tasks/DataProviders.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/DataProviders.java deleted file mode 100644 index 0cf21aaf433..00000000000 --- a/test/micro/org/openjdk/bench/java/util/stream/tasks/DataProviders.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.openjdk.bench.java.util.stream.tasks; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.stream.Stream; - -public class DataProviders { - public static Stream dictionary() throws IOException { - BufferedReader r = new BufferedReader(new InputStreamReader(DataProviders.class.getResourceAsStream("cmudict-0.7b.txt"))); - // Strip out the copyright notice and special chars - return r.lines().filter(w -> w.charAt(0) >= 'A' && w.charAt(0) <= 'Z').map(w -> w.substring(0, w.indexOf(" "))).onClose(() -> { - try { - r.close(); - } catch (IOException e) { - // swallow - } - }); - } -} diff --git a/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Bulk.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Bulk.java deleted file mode 100644 index b29d4e82e65..00000000000 --- a/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Bulk.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.openjdk.bench.java.util.stream.tasks.DictionaryWordValue; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Level; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.Arrays; -import java.util.concurrent.RecursiveTask; -import java.util.concurrent.TimeUnit; -import java.util.function.BinaryOperator; -import java.util.function.Function; - - -/** - * Bulk scenario: searching max "wordValue" through the dictionary (array of strings). - */ -@BenchmarkMode(Mode.Throughput) -@Warmup(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS) -@Fork(value = 3) -@OutputTimeUnit(TimeUnit.SECONDS) -@State(Scope.Benchmark) -public class Bulk { - - @Setup(Level.Trial) - public void loadData() { - // cause classload and problem initialization - DictionaryProblem.class.getName(); - } - - @Benchmark - public int hm_seq() { - int max = 0; - for (String s : DictionaryProblem.get()) { - int v = DictionaryProblem.wordValue(s); - if (v > max) { - max = v; - } - } - return max; - } - - @Benchmark - public int hm_par() { - return new Task(DictionaryProblem.get(), 0, DictionaryProblem.get().length).invoke(); - } - - @Benchmark - public int bulk_seq_inner() { - return Arrays.stream(DictionaryProblem.get()) - .map(new Function() { - @Override - public Integer apply(String s) { - return DictionaryProblem.wordValue(s); - } - }) - .reduce(0, new BinaryOperator() { - @Override - public Integer apply(Integer l, Integer r) { - return l > r ? l : r; - } - }); - } - - @Benchmark - public int bulk_par_inner() { - return Arrays.stream(DictionaryProblem.get()).parallel() - .map(new Function() { - @Override - public Integer apply(String s) { - return DictionaryProblem.wordValue(s); - } - }) - .reduce(0, new BinaryOperator() { - @Override - public Integer apply(Integer l, Integer r) { - return l > r ? l : r; - } - }); - } - - - public static class Task extends RecursiveTask { - private static final int FORK_LIMIT = 500; - - private final String[] words; - private final int start, end; - - Task(String[] w, int start, int end) { - this.words = w; - this.start = start; - this.end = end; - } - - @Override - protected Integer compute() { - int size = end - start; - if (size > FORK_LIMIT) { - int mid = start + size / 2; - Task t1 = new Task(words, start, mid); - Task t2 = new Task(words, mid, end); - t1.fork(); - Integer v2 = t2.invoke(); - Integer v1 = t1.join(); - return Math.max(v1, v2); - } else { - int max = 0; - for (int i = start; i < end; i++) { - int v = DictionaryProblem.wordValue(words[i]); - if (v > max) { - max = v; - } - } - return max; - } - } - } - - -} diff --git a/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/DictionaryProblem.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/DictionaryProblem.java deleted file mode 100644 index 8c3b215a3b5..00000000000 --- a/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/DictionaryProblem.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.openjdk.bench.java.util.stream.tasks.DictionaryWordValue; - -import org.openjdk.bench.java.util.stream.tasks.DataProviders; - -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class DictionaryProblem { - - private static final int DICTIONARY_REPEAT_RATE = 40; - - private static final String[] dict; - - static { - int size; - int idx = 0; - List d = Collections.emptyList(); - try (Stream s = DataProviders.dictionary()) { - d = s.collect(Collectors.toList()); - } catch (Exception e) { - // ignore - } - size = d.size() * DICTIONARY_REPEAT_RATE; - dict = new String[size]; - for (int i = 0; i < DICTIONARY_REPEAT_RATE; i++) { - d.sort(new IdxComparator(i)); - for (String s : d) { - // copy the whole string - dict[idx++] = new String(s.toCharArray()); - } - } - assert (idx == dict.length); - } - - public static String[] get() { - return dict; - } - - /** - * A word value is the sum of alphabet value of each characters in a word. - * - * @param word The word - * @return The word value - */ - public static int wordValue(String word) { - char[] ar = word.toLowerCase().toCharArray(); - int value = 0; - for (char c: ar) { - int v = c - 'a' + 1; - if (v < 1 || v > 26) { - // skip non-alphabet - continue; - } - value += (c - 'a' + 1); - } - return value; - } - - static class IdxComparator implements Comparator { - private final int index; - - public IdxComparator(int i) { - index = i; - } - - @Override - public int compare(String a, String b) { - if (a.length() > index && b.length() > index) { - return (a.charAt(index) - b.charAt(index)); - } else { - return (a.length() - b.length()); - } - } - } - -} diff --git a/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Lambda.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Lambda.java deleted file mode 100644 index 4a60523b9a1..00000000000 --- a/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Lambda.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.openjdk.bench.java.util.stream.tasks.DictionaryWordValue; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Level; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.Arrays; -import java.util.concurrent.TimeUnit; - -/** - * Bulk scenario: searching max "wordValue" through the dictionary (array of strings). - */ -@BenchmarkMode(Mode.Throughput) -@Warmup(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS) -@Fork(value = 3) -@OutputTimeUnit(TimeUnit.SECONDS) -@State(Scope.Benchmark) -public class Lambda { - - @Setup(Level.Trial) - public void loadData() { - // cause classload and problem initialization - DictionaryProblem.class.getName(); - } - - public static Integer maxInt(Integer l, Integer r) { - return l > r ? l : r; - } - - @Benchmark - public int bulk_seq_lambda() { - return Arrays.stream(DictionaryProblem.get()) - .map(s -> DictionaryProblem.wordValue(s)) - .reduce(0, (l, r) -> l > r ? l : r); - } - - @Benchmark - public int bulk_seq_mref() { - return Arrays.stream(DictionaryProblem.get()) - .map(DictionaryProblem::wordValue) - .reduce(0, Lambda::maxInt); - } - - @Benchmark - public int bulk_par_lambda() { - return Arrays.stream(DictionaryProblem.get()).parallel() - .map(s -> DictionaryProblem.wordValue(s)) - .reduce(0, (l, r) -> l > r ? l : r); - } - - @Benchmark - public int bulk_par_mref() { - return Arrays.stream(DictionaryProblem.get()).parallel() - .map(DictionaryProblem::wordValue) - .reduce(0, Lambda::maxInt); - } - -} diff --git a/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Xtras.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Xtras.java deleted file mode 100644 index 9f1c05857e2..00000000000 --- a/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Xtras.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.openjdk.bench.java.util.stream.tasks.DictionaryWordValue; - -/** - * Bulk scenario: searching max "wordValue" through the dictionary (array of strings). - */ -public class Xtras { - - // no workloads yet - -} diff --git a/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/Bulk.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/Bulk.java deleted file mode 100644 index 7040092962e..00000000000 --- a/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/Bulk.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.openjdk.bench.java.util.stream.tasks.PhoneCode; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import static org.openjdk.bench.java.util.stream.tasks.PhoneCode.PhoneCodeProblem.wordsForNumber; - -/** - * This benchmark compare various strategies solving the phone code problem. - * The result should offer some insights on strength/drawbacks of underlying - * implementation. - */ -@BenchmarkMode(Mode.Throughput) -@Warmup(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS) -@Fork(value = 3) -@OutputTimeUnit(TimeUnit.MINUTES) -@State(Scope.Benchmark) -public class Bulk { - // several method choke up with 6-digit problem - private final static int SIZE = 5; - private Stream join(String head, - String tail, - Function> encoder) - { - Stream s = wordsForNumber(head).stream(); - - if (! tail.isEmpty()) { - s = s.flatMap(h -> encoder.apply(tail).map(t -> h + " " + t)); - } - - return s; - } - - private Stream encode_par1(String number) { - return IntStream.range(1, number.length() + 1) - .parallel() - .boxed() - .flatMap(i -> join(number.substring(0, i), - number.substring(i), - this::encode_par1)); - } - - private Stream encode_par2(String number) { - return IntStream.range(1, number.length() + 1) - .boxed() - .parallel() - .flatMap(i -> join(number.substring(0, i), - number.substring(i), - this::encode_par2)); - } - - private Stream encode_ser(String number) { - return IntStream.range(1, number.length() + 1) - .boxed() - .flatMap(i -> join(number.substring(0, i), - number.substring(i), - this::encode_ser)); - } - - private Stream encode_loop_concat(String number) { - if (number.isEmpty()) { - return Stream.empty(); - } - // full number - Stream s = wordsForNumber(number).stream(); - // split - for (int i = 1; i < number.length(); i++) { - s = Stream.concat(s, join(number.substring(0, i), - number.substring(i), - this::encode_loop_concat)); - } - - return s; - } - - private Collection encode_loop_collect(String number) { - if (number.isEmpty()) { - return Collections.emptySet(); - } - - Collection rv = new HashSet<>(); - - for (int i = 1; i <= number.length(); i++) { - join(number.substring(0, i), - number.substring(i), - s -> encode_loop_collect(s).stream()).forEach(rv::add); - } - - return rv; - } - - private Collection encode_inline(String number) { - if (number.isEmpty()) { - return Collections.emptySet(); - } - - Collection rv = new HashSet<>(); - - for (int i = 1; i < number.length(); i++) { - String front = number.substring(0, i); - String rest = number.substring(i); - wordsForNumber(front).stream() - .flatMap(h -> encode_inline(rest).stream().map(t -> h + " " + t)) - .forEach(rv::add); - } - - rv.addAll(wordsForNumber(number)); - - return rv; - } - - @Benchmark - public int bulk_par_range_concurrent() { - // force collect - return PhoneCodeProblem.get(SIZE) - .flatMap(this::encode_par1) - .collect(Collectors.toConcurrentMap( - Function.identity(), - Function.identity(), - (l, r) -> l)) - .keySet() - .size(); - } - - @Benchmark - public int bulk_par_boxed_range_concurrent() { - // force collect - return PhoneCodeProblem.get(SIZE) - .flatMap(this::encode_par2) - .collect(Collectors.toConcurrentMap( - Function.identity(), - Function.identity(), - (l, r) -> l)) - .keySet() - .size(); - } - - @Benchmark - public int bulk_par_range() { - // force collect - return PhoneCodeProblem.get(SIZE) - .flatMap(this::encode_par1) - .collect(Collectors.toSet()) - .size(); - } - - @Benchmark - public int bulk_par_boxed_range() { - // force collect - return PhoneCodeProblem.get(SIZE) - .flatMap(this::encode_par2) - .collect(Collectors.toSet()) - .size(); - } - - @Benchmark - public int bulk_ser_range() { - // force collect - return PhoneCodeProblem.get(SIZE) - .flatMap(this::encode_ser) - .collect(Collectors.toSet()) - .size(); - } - - @Benchmark - public int bulk_ser_loop_concat() { - // force collect - return PhoneCodeProblem.get(SIZE) - .flatMap(this::encode_loop_concat) - .collect(Collectors.toSet()) - .size(); - } - - @Benchmark - public int bulk_ser_loop_collect() { - return PhoneCodeProblem.get(SIZE) - .map(this::encode_loop_collect) - .map(Collection::size) - .reduce(0, Integer::sum); - } - - @Benchmark - public int bulk_ser_inline() { - return PhoneCodeProblem.get(SIZE) - .map(this::encode_inline) - .map(Collection::size) - .reduce(0, Integer::sum); - } -} diff --git a/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/PhoneCodeProblem.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/PhoneCodeProblem.java deleted file mode 100644 index 98458a662bb..00000000000 --- a/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/PhoneCodeProblem.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.openjdk.bench.java.util.stream.tasks.PhoneCode; - -import org.openjdk.bench.java.util.stream.tasks.DataProviders; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * The phone coder problem is trying to find full list of possible - * mnemonic combination of numbers. - * - * The solution is based on Martin Odersky's devoxx 2010 scala talk, - * where numbers are not allowed in the result, which is not really - * correct, but we don't care. - */ -public class PhoneCodeProblem { - // Map Character 'A'-'Z' to digits "2"-"9", key is charCode - private static final Map CHAR_CODE; - // Map a string of digits to a collection of dictionary words - private static final Map> WORD_CODES; - - static { - HashMap mnemonics = new HashMap<>(8); - mnemonics.put("2", "ABC"); - mnemonics.put("3", "DEF"); - mnemonics.put("4", "GHI"); - mnemonics.put("5", "JKL"); - mnemonics.put("6", "MNO"); - mnemonics.put("7", "PQRS"); - mnemonics.put("8", "TUV"); - mnemonics.put("9", "WXYZ"); - - CHAR_CODE = new ConcurrentHashMap<>(); - mnemonics.entrySet().stream().forEach(e -> - e.getValue().chars().forEach(c -> - { CHAR_CODE.put(c, e.getKey()); } )); - - WORD_CODES = loadDictionary(); - // System.out.println("Dictionary loaded with " + WORD_CODES.size() + " number entries"); - } - - // Convert a word to its number form - private static String wordToNumber(String word) { - return word.chars().mapToObj(CHAR_CODE::get) - .reduce("", String::concat); - } - - // Prepare number -> word lookup table - private static Map> loadDictionary() { - try (Stream s = DataProviders.dictionary()) { - return s.filter(w -> w.length() > 1) - .filter(w -> w.matches("[a-zA-Z]*")) - .map(String::toUpperCase) - .collect(Collectors.groupingBy(PhoneCodeProblem::wordToNumber)); - } catch (Exception ex) { - ex.printStackTrace(System.err); - return Collections.emptyMap(); - } - } - - public static Collection wordsForNumber(String number) { - Collection rv = WORD_CODES.get(number); - return (null == rv) ? Collections.emptySet() : rv; - } - - public static Stream get(int length) { - String digits[] = { "2", "3", "4", "5", "6", "7", "8", "9" }; - - Stream s = Arrays.stream(digits); - for (int i = 1; i < length; i++) { - s = s.flatMap(d1 -> Arrays.stream(digits).map(d2 -> d1 + d2)); - } - return s; - } -}