I'm currently working on an exercise to sort only the odd element of an array of int. The program shouldn't affect the even elements, For example:
[5, 3, 8, 0, 1] --> [1, 3, 8, 0, 5]
However, when I run the following code, the compiler gives the following error:
Main.java:21: error: ')' expected
int [] res = Arrays.asList(array).stream().mapToInt((x[0]) -> x[0]%2 == 0 ? x[0] : listInt.get( j)).collect(Collectors.toList()).toArray();
^
Main.java:21: error: not a statement
int [] res = Arrays.asList(array).stream().mapToInt((x[0]) -> x[0]%2 == 0 ? x[0] : listInt.get( j)).collect(Collectors.toList()).toArray();
^
Main.java:21: error: ';' expected
int [] res = Arrays.asList(array).stream().mapToInt((x[0]) -> x[0]%2 == 0 ? x[0] : listInt.get( j)).collect(Collectors.toList()).toArray();
^
3 errors
Here's my code:
public static void main(String[] args) {
int[] array = new int[]{ 5, 3, 1, 8, 0 };
int j = 0;
List<Integer> listInt = Arrays.stream(array).filter(x -> x%2 != 0).sorted().boxed().collect(Collectors.toList());
int [] res = Arrays.asList(array).stream().mapToInt(x -> x%2 == 0 ? x : listInt.get( j)).collect(Collectors.toList()).toArray();
}
Could you help me to fix those error?
CodePudding user response:
In your statement with Arrays.asList(array) you're creating a List where each element is an array of int, so when you're streaming the List, the stream expects each element to be int[], not int. In your case, the stream only contains the array variable. When you're performing x -> x % 2 == 0, you're not applying it on the array's elements but on the array itself; thus giving you the error.
Besides, lambda expressions only allow to use final or effectively final variables, i.e. variables whose value does not change. Your j expression within the stream won't be accepted either.
This is a fixed version of your code:
public class Main {
public static void main(String[] args) {
int[] array = new int[]{5, 3, 1, 8, 0};
//Passing to list returned by the stream to a PriorityQueue to store the odd numbers sorted with their natural order.
//In this way, there is no need to sort the elements within the stream and we can use the queue as an effectively final variable while still polling its elements
PriorityQueue<Integer> queue = new PriorityQueue<>(Arrays.stream(array).filter(x -> x % 2 != 0).boxed().collect(Collectors.toList()));
//Declaring and initializing the result array in order to pass it to the toArray method
Integer[] res = new Integer[0];
//For each element of the stream we return the even numbers while we pop the odd sorted numbers from the queue
res = Arrays.stream(array).boxed().map(x -> x % 2 == 0 ? x : queue.poll()).collect(Collectors.toList()).toArray(res);
//Printing the result on screen
System.out.println(Arrays.toString(res));
}
}
CodePudding user response:
There are essentially 3 changes you need to make:
- Change
Arrays.stream(array)toIntStream.of(array) - Change
int j = 0;toint[] j = {0}; - Change
jtoj[0]
The first change is needed because Arrays.stream(array) creates a stream of int[] with 1 element, but you want a stream of int, so use IntStream directly.
The second change is more subtle. Because all terms in a lambda must be effectively final - ie you can't change their value - j won't compile. By making j an int[] you can change its contents without changing the reference to j.
The third change is a logic problem: j (or j[0] in the new version) increments before its use and so will cause an out of bounds exception for the final operation.
Your code fixed:
int[] j = {0};
int[] odds = IntStream.of(array).filter(x -> x%2 != 0).sorted().toArray();
int [] res = IntStream.of(array).map(x -> x%2 == 0 ? x : odds[j[0] ]).toArray();
Note that you don't need to box int to Integer, and I renamed the cryptic listInt to odds for readability.
The "proper" solution is to change j to AtomicInteger - similarly the reference to j won't change, but its contents may change:
AtomicInteger j = new AtomicInteger();
int[] odds = IntStream.of(array).filter(x -> x%2 != 0).sorted().toArray();
int [] res = IntStream.of(array).map(x -> x%2 == 0 ? x : odds[j.getAndIncrement()]).toArray();
