'How to do this string pattern aaabbc to be displayed as 3a2b1c in java 8 using streams
I want to display the String pattern aaabbcc
to be displayed as 3a2b2c
in java8 using streams
I have a working example in lower versions
String str = "aabbcccddd";
String chars[] = str.split("");
Map<String, Integer> compressMap = new LinkedHashMap<String, Integer>();
for(String s: chars) {
if("".equals(s))
continue;
Integer count = compressMap.get(s);
if(count != null)
compressMap.put(s, ++count);
else
compressMap.put(s, 1);
}
StringBuffer output = new StringBuffer("");
for (Map.Entry<String, Integer> entry : compressMap.entrySet()) {
output.append(entry.getValue()).append(entry.getKey());
}
System.out.println(output);
can anyone help on this?
Solution 1:[1]
What you did will still work on Java 8, but you can simplify your code by relying on Stream
as next:
String str = "aabbcccddd";
// Convert the String into a Stream
// Convert int into Character
// Group by Character and count occurrences
// For each entry add the key (Character) followed by the value (Occurrences) to the result
// using the joining collector
String output = str.chars()
.mapToObj(i -> (char)i)
.collect(groupingBy(Function.identity(), LinkedHashMap::new, counting()))
.entrySet()
.stream()
.flatMap(entry -> Stream.of(entry.getValue().toString(), entry.getKey().toString()))
.collect(Collectors.joining());
System.out.println(output);
Output:
2a2b3c3d
Another approach slightly different where we convert Integer
to char
at the end:
String output = str.chars()
.boxed()
.collect(groupingBy(Function.identity(), LinkedHashMap::new, counting()))
.entrySet()
.stream()
.flatMap(entry -> Stream.of(entry.getValue().toString(), Character.toString((char) entry.getKey().intValue())))
.collect(Collectors.joining());
NB: I use LinkedHashMap::new
as supplier instead of the default HashMap::new
to preserve the order.
Solution 2:[2]
The other solution will be:
String output = Pattern.compile("(?<=(\\w))(?!\\1)")
.splitAsStream(string)
.map(part -> part.length() + part.substring(0, 1))
.collect(Collectors.joining());
The Pattern (?<=(\\w))(?!\\1)
match places in String where next char is different than previous, so it split String into parts containing separate letters, then map it to string with its length.
Solution 3:[3]
Here is the code for above problem: Time complexity: O(n) Space complexity: O(1)
private void printCharacterLength(char[] arr) {
StringBuilder result = new StringBuilder();
int count = 1;
for (int i = 1; i < arr.length; i++) {
if (arr[i] == arr[i - 1]) {
count++;
} else {
result.append((count > 1 ? count : "")).append(arr[i - 1]);
count = 1;
}
}
result.append((count > 1 ? count : "")).append(arr[arr.length - 1]);
System.out.println(result);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | m.cekiera |
Solution 3 | user11016 |