Namings
First, make sure names describe the thing they name. the class CountSpaces
does nothing of the sort, it reverses Strings.
st
, st1
and x
are all the String to reverse. If you had a method that did this, the String could be called input
but original
works for both cases.
stringPositionArray
is a List
, not an array. In any case, adding the type as a suffix is unnecessary. Just call it stringIndexes
, as index is the word normally used for that number. And you only use contains()
which is faster with a HashSet
Unnecessary variables
flag
is only used to see if sub
should be subtracted or not. It always has the same value as sub
and only avoids subtracting sub
when it's zero. You could simply always subtract sub
.
char y = x[i]
could be avoided with using x[i]
on the next row. And x
is unnecessary as you can use String.charAt
.
len
is only used once for each time it's assigned. That too could be replaced with x.length
or original.length()
if you use a String.
For loops can contain multiple variables, so k
can be inserted in the loop declaration like
for (int i = len - 1, k = 1; i >= 0; i--, k++)
The second loop always prints x[i]
, only the space is conditional. Also, always use the {}. And concat a String instead of printing each char.
So far, your main method should look like
public static void main(String[] args) { String original = "best in the world and is greatest and is making sure the world goes well"; Set<Integer> spaceIndexes = new HashSet<>(); for (int i = 1, sub = 0; i < original.length(); i++) { if (original.charAt(i) == ' ') { spaceIndexes.add(i - sub++); } } String noSpaces = original.replaceAll("\\s+", ""); String reversed = ""; for (int i = noSpaces.length() - 1, k = 1; i >= 0; i--, k++) { reversed += noSpaces.charAt(i); if(spaceIndexes.contains(k)) { reversed += " "; } } System.out.println(reversed); System.out.println(original); }
Tools
Java has loads of tools to handle Strings and more general collections of things. StringBuilder has methods for reversing a String and inserting chars in the middle. A nice trick for getting the indexes matching some condition is using IntStream.range()
and filter()
.
StringBuilder reversed = new StringBuilder(input.replaceAll(" ", "")).reverse(); IntStream.range(0, input.length()) .filter(i -> input.charAt(i) == ' ') .forEach(i -> reversed.insert(i, " "));
Avoid using indexes
Indexes can cause annoying off-by-one errors. If you can do operations on an entire array, list or stream, do so. You can potentially use Iterator
s to traverse things when you have more than one collection to handle.
Iterator<Integer> reverse = new StringBuilder(original.replaceAll(" ","")) .reverse() .chars() .iterator(); String output = original .chars() .mapToObj(c -> c == ' ' ? " " : Character.toString(reverse.next())) .collect(Collectors.joining());