I'm trying to write a method that will validate String. If string has same amount of every char like "aabb", "abcabc", "abc" it is valid or if contains one extra symbol like "ababa" or "aab" it is also valid other cases - invalid.
Update: sorry, I forget to mention such cases like abcabcab -> a-3, b-3, c-2 -> 2 extra symbols (a, b) -> invalid. And my code doesn't cover such cases.
Space is a symbol, caps letters are different from small letters. Now I have this, but it looks ambiguous (especially last two methods):
public boolean validate(String line) {
List<Long> keys = countMatches(countChars(line));
int matchNum = keys.size();
if (matchNum < 2) return true;
return matchNum == 2 && Math.abs(keys.get(0) - keys.get(1)) == 1;
}
Counting unique symbols entry I'd wish to get List<long>, but I don't know how:
private Map<Character, Long> countChars(String line) {
return line.chars()
.mapToObj(c -> (char) c)
.collect(groupingBy(Function.identity(), HashMap::new, counting()));
}
private List<Long> countMatches(Map<Character, Long> countedEntries) {
return new ArrayList<>(countedEntries.values()
.stream()
.collect(groupingBy(Function.identity(), HashMap::new, counting()))
.keySet());
}
How can I optimize a method above? I need just List<Long>, but have to create a map.
charis a sixteen bit integral type in Java. If you know there will be some huge number of characters in the input string (or you know it's limited to US-ASCII) you could use along[256]orlong[65536]array and index by the character. Then you could return along[]instead of aList<Long>. Are you familiar with the expression "premature optimization is the root of all evil?"countMatcheseventually tries to find out the distinct values from the suppliedMapby creating a map and that too counting the occurrences and then discarding the values of the newly created map altogether. Which s just a matter ofnew HashSet<>(map.values()), but then the output desired isListand that's mostly since the OP is trying to access indexes to validate the values in the later phase.long[]is going to perform better than aSet(hence my premature optimization comment). If nothing else, it avoids the boxing of the counts toLong(which is not a trivial cost here - for long enough strings).Stringlength, which is anint, there is no need to uselongfor the counts.abcabcabas it only checks if the difference between the char-lengths is 1matchNum == 2 && Math.abs(keys.get(0) - keys.get(1)) == 1. as you said 3a 3b 2c. in this case the char-length diff is one (3-2), but twice, so it returns valid instead of invalid