I am currently working with Java and practicing my programming logic and as a good practice I am trying to apply stream in some operations with Java collections.
In this case I have a method that receives a string and a set list, the string must be taken to a list to replace its characters according to the values found in the Set, once replaced they are taken back to string and It is returned:
private static String wordToGuess(String word,List<Integer> valueUniqueToRemplace){
List<String> wordToList=new ArrayList<>(Arrays.asList(word.split("")));
for (Integer integer : valueUniqueToRemplace) {
wordToList.set(integer, "_");
}
return wordToList.stream().map(String::valueOf).collect(Collectors.joining(""));
}
How could I replace the for loop and what is done within it with a stream function?
as a good practice I am trying to apply stream in some operations with Java collections
Practice is good but also notice when it makes sense to use a certain language construct and when not. Not every task is suitable to be solved with streams. If I see it correctly, you are trying to replace certain indices of a string with underscores. This is not clear, at least at first glance at your method. I would have written something like below, which is easier to understand:
private static String wordToGuess1(String word,List<Integer> valueUniqueToReplace){
char[] chars = word.toCharArray();
valueUniqueToReplace.forEach(i -> chars[i] = '_');
return String.valueOf(chars);
}
or
private static String wordToGuess2(String word,List<Integer> valueUniqueToReplace){
StringBuilder sb = new StringBuilder(word);
valueUniqueToReplace.forEach(i -> sb.setCharAt(i, '_'));
return sb.toString();
}
There are certainly better approaches but spontaneously I think of the following alternatives with streams:
private static String wordToGuess3(String word,List<Integer> valueUniqueToReplace){
return IntStream.range(0, word.length())
.map(i -> valueUniqueToReplace.contains(i) ? '_' : word.charAt(i))
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
}
private static String wordToGuess4(String word,List<Integer> valueUniqueToReplace){
return valueUniqueToReplace.stream()
.reduce(new StringBuilder(word),
(sb, i) -> sb.replace(i, i + 1, "_"),
(a,b) -> a)
.toString();
}
Decide for yourself what is more readable, I for one would prefer the non stream approach