import java.util.*;
class WordCounter {
public static Map
<String, Integer
> countWords
(String text
) { Map
<String, Integer
> countsByNormalized
= new HashMap
<>(); Map
<String, String
> displayByNormalized
= new HashMap
<>();
if (text == null || text.isBlank()) {
}
String[] tokens
= text.
split("\\s+"); if (raw == null || raw.isEmpty()) continue;
String normalized
= originalLower.
replaceAll("^[^\\p{L}\\p{N}]+|[^\\p{L}\\p{N}]+$",
"");
if (normalized.isEmpty()) continue;
displayByNormalized.putIfAbsent(normalized, originalLower);
countsByNormalized.put(normalized, countsByNormalized.getOrDefault(normalized, 0) + 1);
}
Map
<String, Integer
> result
= new LinkedHashMap
<>(); for (Map.
Entry<String, Integer
> e
: countsByNormalized.
entrySet()) { String normalized
= e.
getKey(); String display
= displayByNormalized.
get(normalized
); result.put(display, e.getValue());
}
return result;
}
public static void printSortedByKey
(Map
<String,Integer
> map
) { map.entrySet().stream()
.
forEach(e
-> System.
out.
println(e.
getKey() + " → " + e.
getValue())); }
public static void main
(String[] args
) { String input
= "This is a test. This is only a test"; Map
<String, Integer
> counts
= countWords
(input
);
printSortedByKey(counts);
}
}
aW1wb3J0IGphdmEudXRpbC4qOwoKY2xhc3MgV29yZENvdW50ZXIgewoKICAgIHB1YmxpYyBzdGF0aWMgTWFwPFN0cmluZywgSW50ZWdlcj4gY291bnRXb3JkcyhTdHJpbmcgdGV4dCkgewogICAgICAgIE1hcDxTdHJpbmcsIEludGVnZXI+IGNvdW50c0J5Tm9ybWFsaXplZCA9IG5ldyBIYXNoTWFwPD4oKTsKICAgICAgICBNYXA8U3RyaW5nLCBTdHJpbmc+IGRpc3BsYXlCeU5vcm1hbGl6ZWQgPSBuZXcgSGFzaE1hcDw+KCk7CgogICAgICAgIGlmICh0ZXh0ID09IG51bGwgfHwgdGV4dC5pc0JsYW5rKCkpIHsKICAgICAgICAgICAgcmV0dXJuIENvbGxlY3Rpb25zLmVtcHR5TWFwKCk7CiAgICAgICAgfQoKICAgICAgICBTdHJpbmdbXSB0b2tlbnMgPSB0ZXh0LnNwbGl0KCJcXHMrIik7CiAgICAgICAgZm9yIChTdHJpbmcgcmF3IDogdG9rZW5zKSB7CiAgICAgICAgICAgIGlmIChyYXcgPT0gbnVsbCB8fCByYXcuaXNFbXB0eSgpKSBjb250aW51ZTsKCiAgICAgICAgICAgIFN0cmluZyBvcmlnaW5hbExvd2VyID0gcmF3LnRvTG93ZXJDYXNlKExvY2FsZS5ST09UKTsKCiAgICAgICAgICAgIFN0cmluZyBub3JtYWxpemVkID0gb3JpZ2luYWxMb3dlci5yZXBsYWNlQWxsKCJeW15cXHB7TH1cXHB7Tn1dK3xbXlxccHtMfVxccHtOfV0rJCIsICIiKTsKCiAgICAgICAgICAgIGlmIChub3JtYWxpemVkLmlzRW1wdHkoKSkgY29udGludWU7CgogICAgICAgICAgICBkaXNwbGF5QnlOb3JtYWxpemVkLnB1dElmQWJzZW50KG5vcm1hbGl6ZWQsIG9yaWdpbmFsTG93ZXIpOwoKICAgICAgICAgICAgY291bnRzQnlOb3JtYWxpemVkLnB1dChub3JtYWxpemVkLCBjb3VudHNCeU5vcm1hbGl6ZWQuZ2V0T3JEZWZhdWx0KG5vcm1hbGl6ZWQsIDApICsgMSk7CiAgICAgICAgfQoKICAgICAgICBNYXA8U3RyaW5nLCBJbnRlZ2VyPiByZXN1bHQgPSBuZXcgTGlua2VkSGFzaE1hcDw+KCk7CiAgICAgICAgZm9yIChNYXAuRW50cnk8U3RyaW5nLCBJbnRlZ2VyPiBlIDogY291bnRzQnlOb3JtYWxpemVkLmVudHJ5U2V0KCkpIHsKICAgICAgICAgICAgU3RyaW5nIG5vcm1hbGl6ZWQgPSBlLmdldEtleSgpOwogICAgICAgICAgICBTdHJpbmcgZGlzcGxheSA9IGRpc3BsYXlCeU5vcm1hbGl6ZWQuZ2V0KG5vcm1hbGl6ZWQpOwogICAgICAgICAgICByZXN1bHQucHV0KGRpc3BsYXksIGUuZ2V0VmFsdWUoKSk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBwcmludFNvcnRlZEJ5S2V5KE1hcDxTdHJpbmcsSW50ZWdlcj4gbWFwKSB7CiAgICAgICAgbWFwLmVudHJ5U2V0KCkuc3RyZWFtKCkKICAgICAgICAgICAgICAgIC5zb3J0ZWQoTWFwLkVudHJ5LmNvbXBhcmluZ0J5S2V5KCkpCiAgICAgICAgICAgICAgICAuZm9yRWFjaChlIC0+IFN5c3RlbS5vdXQucHJpbnRsbihlLmdldEtleSgpICsgIiDihpIgIiArIGUuZ2V0VmFsdWUoKSkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpIHsKICAgICAgICBTdHJpbmcgaW5wdXQgPSAiVGhpcyBpcyBhIHRlc3QuIFRoaXMgaXMgb25seSBhIHRlc3QiOwogICAgICAgIE1hcDxTdHJpbmcsIEludGVnZXI+IGNvdW50cyA9IGNvdW50V29yZHMoaW5wdXQpOwoKICAgICAgICBwcmludFNvcnRlZEJ5S2V5KGNvdW50cyk7CiAgICB9Cn0KCgo=