5

I want to optimize this solution (idiomatically).

I have a string containing only integer values. I want to convert this string into reverse int array. The output should be an integer array

Here is my solution:

private static int[] stringToReversedIntArray(String num) {
    int[] a = new int[num.length()];
    for (int i = 0; i < num.length(); i++) {
        a[i] = Integer.parseInt(num.substring(i, i + 1));
    }
    a = reverse(a);
    return a;
}

/*
 * Reverses an int array
 */
private static int[] reverse(int[] myArray) {
    int[] reversed = new int[myArray.length];
    for (int i = 0; i < myArray.length; i++) {
        reversed[i] = myArray[myArray.length - (i + 1)];
    }
    return reversed;
}

Input: "1256346258"
Output: {8,5,2,6,4,3,6,5,2,1}

Please suggest how to do same.

3
  • What 'standard library method calls' have you tried? Have you done any research to see what is available? Commented Jun 17, 2019 at 7:01
  • 2
    reverse at the same time you decode the original string : a[num.length()-i-1] = num.charAt(i)-'0'; Commented Jun 17, 2019 at 7:18
  • 1
    This question appears to have an already working solution by OP. It may be better suited for codereview.stackexchange.com. Commented Jun 17, 2019 at 7:29

8 Answers 8

3
var input = "1256346258";
var result = Arrays
        .stream(new StringBuffer(input).reverse().toString().split(""))
        .map(Integer::parseInt)
        .collect(Collectors.toList());
System.out.println(result);
Sign up to request clarification or add additional context in comments.

3 Comments

StringBuffer → StringBuilder
@ZhekaKozlov StringBuilder can be replaced by StringBuffer where synchronization is not required, like discussed here
It can be but it shouldn't
2

Since you are extracting one character at a time, using charAt instead of substring makes more sense.

And since you are converting a single character to an int, Character.getNumericValue() makes more sense then parseInt.

Hence I'd change

a[i] = Integer.parseInt(num.substring(i, i + 1));

to

a[i] = Character.getNumericValue(num.charAt(i));

You can also simplify the reverse part as follows if you don't mind using an Integer[] instead of int[]:

private static Integer[] stringToReversedIntArray(String num) {
    Integer[] a = new Integer[num.length()];
    for (int i = 0; i < num.length(); i++) {
        a[i] = Character.getNumericValue(num.charAt(i));
    }
    Collections.reverse(Arrays.asList(a));
    return a;
}

3 Comments

Small note about getNumericValue. It will output weird numeric values if you pass alphabet characters, while parseInt() is a bit safer and throws a NumberFormatException. Of course each is convenient in its own way.
@jbx well, the OP did say string containing only integer values
Yes of course, the solution is perfectly valid. Just included the note for the future reader who would like to use this option. Because it is easy to miss this subtle difference.
0

One-liner:

return IntStream
    .range(0, num.length())
    .map(i -> Character.getNumericValue(num.charAt(num.length() - i - 1)))
    .toArray();

Comments

0

No need to loop 2 times, you can use StringBuilder to reverse a String, and then loop over it to store the result in your int array:

  private static int[] stringToReversedIntArray(String num) {
    num = new StringBuilder(num).reverse().toString();
    int[] result = new int[num.length()]; 
    for (int i = 0; i < result.length; i++){
      result[i] = Character.getNumericValue(num.charAt(i)); 
    }
    return result;
  }

Other options would either be to just reverse your for loop and have it count backwards:

for(int i = array.length - 1; i >= 0; i--){
  ...
}

Or use the Stream API in recent versions of Java, as has already been mentioned above in a nice example.

Comments

0

If you want to use streams you can do it with something like this:

Deque<String> deque = num.chars()
   .map(c -> Character.toString((char) c))
   .map(Integer::parseInt)
   .collect(Collector.of(
        ArrayDeque::new,
        (stack, i) -> stack.addFirst(i),
        (s1, s2) -> { s2.addAll(s1); return s2; })); //this combiner won't really be called unless the stream was parallel

Integer[] reversed = deque.toArray(new Integer[deque.size()]);

This loops through the list just once. The Deque can work as a stack, Last In First Out, so each addFirst() will automatically reverse the order since it adds each item to the front not the back of the list. You can convert it to an array afterwards, or use the Deque as is, which is a normal Collection and implements Iterable.

As other answers mentioned, you could also simplify it a bit like this, if you are 100% sure you have only digits, because with the simplified version you won't get a NumberFormatException.

Deque<String> deque = num.chars()
   .map(c -> Character.getNumericValue((char) c))
   .collect(Collector.of(
        ArrayDeque::new,
        (stack, i) -> stack.addFirst(i),
        (s1, s2) -> { s2.addAll(s1); return s2; }));

Integer[] reversed = deque.toArray(new Integer[deque.size()]);

Comments

0
String str = "123456";
// Reverse String
str = new StringBuilder(str).reverse().toString();
String strArr[] = str.split("(?!^)");
// Convert to Int Array
int[] intarray = java.util.Arrays.stream(strings).mapToInt(Integer::parseInt).toArray();

Comments

0

Erans solution is fine to me, but i dont like the for loop and i prefer if possible the stream api

String testString = "1256346258";
IntStream intStream = testString.chars();       
List<Integer> x = intStream.boxed().collect(Collectors.toList());
Collections.reverse(x);
int[] array = x.stream().mapToInt(i -> Character.getNumericValue(i)).toArray();
System.out.println("x: " + Arrays.toString(array));

just wrap it with a nice method...

Comments

0

Here's a simple solution with a single for loop. You can "reverse" the digits at the same time you extract the numeric values, just by playing a bit with the indexes:

private static int[] stringToReversedIntArray(String num) {
    int len = num.length();
    int[] a = new int[len];
    for (int i = 0; i < len; i++) {
        a[i] = Character.getNumericValue(num.charAt(len - i - 1));
    }
    return a;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.