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
j
toj[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();