I’m learning Java 8 streams. Tell me pls, how can I write a sortArray method more compactly?
import org.junit.Test;    
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.assertArrayEquals;
public class TestStream {
    /*
     * Sort numbers in an array without changing even numbers position
     */
    @Test
    public void test_1() {
        int[] nonSorted = new int[]{3, 4, 5, 2, 1, 6, 9, 8, 7, 0};
        int[] expected = new int[]{1, 4, 3, 2, 5, 6, 7, 8, 9, 0};
        Integer[] arr = sortArray(nonSorted);
        int[] sorted = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            sorted[i] = arr[i];
        }
        assertArrayEquals(expected, sorted);
    }
    private Integer[] sortArray(int[] array) {
        Map<Integer, Integer> even = extractEven(array);
        Integer[] withoutEvens = removeEven(array);
        int length = even.size() + withoutEvens.length;
        Integer[] result = new Integer[length];
        Arrays.sort(withoutEvens);
        for (int i = 0; i < withoutEvens.length; i++) {
            result[i] = withoutEvens[i];
        }
        even.forEach((k, v) -> {
            System.arraycopy(result, k, result, k + 1, length - k - 1);
            result[k] = v;
        });
        return result;
    }
    private Map<Integer, Integer> extractEven(int[] array) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < array.length; i++) {
            if (array[i] % 2 == 0) {
                map.put(i, array[i]);
            }
        }
        return map;
    }
    private Integer[] removeEven(int[] array) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        for (int i = 0; i < array.length; i++) {
            if (array[i] % 2 != 0) {
                list.add(array[i]);
            }
        }
        Integer[] a = new Integer[list.size()];
        return list.toArray(a);
    }
}
                One can think of a solution like:
First we extract the odd integers from the nonSorted[] and put them on a stack in sorted fashion.
Why we should use the
stackin a sorted fashion??The final array needs to be sorted on odd
Integersbasis, the stack follows FIFO(First in Last Out) policy.
Now we take an Instream and run it from 0 to nonSorted.length-1 and check the original nonSorted for the odd Integer; as soon as we find one we replace it with the first element of the stack and pop() the element from the stack.
Note: One needs to play around the stack as not every time you will need sorted elements in the stack, but in OP's case this happens to be.
int[] nonSorted = new int[]{3, 4, 5, 2, 1, 6, 9, 8, 7, 0};
LinkedList<Integer> stack = Arrays.stream(nonSorted)
            .sorted().filter(s -> s % 2 != 0).boxed()
            .collect(Collectors.toCollection(LinkedList::new));
int[] expected = IntStream.rangeClosed(0, nonSorted.length - 1)
       .map(s -> nonSorted[s] % 2 != 0 ? stack.pop():nonSorted[s]) 
       .toArray();
                        I really liked the idea of using a sorted Stack, but it is not easily parallelizable and got me curious how to solve that.
My idea is sorting indices of uneven elements and depending on the position of the index we can distinguish during the creation of the result array if a number is even or not.
public int[] sortUnevenElements(int[] nonSorted) {
    int[] unevenIndices = IntStream.range(0, nonSorted.length).filter(i -> nonSorted[i] % 2 != 0).toArray();
    int[] sortedUnevenIndices = Arrays.stream(unevenIndices, 0, unevenIndices.length).boxed()
          .sorted(Comparator.comparingInt(i -> nonSorted[i])).mapToInt(Integer::intValue).toArray();
    return IntStream.range(0, nonSorted.length).map(i -> {
        int idx = Arrays.binarySearch(unevenIndices, i);
        return idx >= 0 ? nonSorted[sortedUnevenIndices[idx]] : nonSorted[i];
    }).toArray();
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With