Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert a collection/ array into JSONArray using stream in java 8

Im having a double array , I need to convert the array into a JSONArray using java streams. I tried using forEach (shared mutability) which leads to loss of data.

public static JSONArray arrayToJson(double[] array) throws JSONException{
    JSONArray jsonArray = new JSONArray();
    
    Arrays.stream(array)
         .forEach(jsonArray::put);  

    return jsonArray;
}

Is there any way I could to create JSONArray using streams?

like image 308
Manikandan Balasubramanian Avatar asked Jan 08 '18 06:01

Manikandan Balasubramanian


People also ask

How do I turn an array into a Stream?

A good way to turn an array into a stream is to use the Arrays class' stream() method. This works the same for both primitive types and objects.

Can we apply Stream on array in Java?

The stream(T[] array) method of Arrays class in Java, is used to get a Sequential Stream from the array passed as the parameter with its elements. It returns a sequential Stream with the elements of the array, passed as parameter, as its source.

What is the difference between JSONObject and JSONArray?

JSONObject and JSONArray are the two common classes usually available in most of the JSON processing libraries. A JSONObject stores unordered key-value pairs, much like a Java Map implementation. A JSONArray, on the other hand, is an ordered sequence of values much like a List or a Vector in Java.

Which method is used to convert the elements of a Stream to a single value?

Stream can be converted into Set using forEach(). Loop through all elements of the stream using forEach() method and then use set.


1 Answers

Your code works, but you can write something like this (jdk 8+):

return Arrays.stream(array)
             .collect(Collector.of(
                          JSONArray::new, //init accumulator
                          JSONArray::put, //processing each element
                          JSONArray::put  //confluence 2 accumulators in parallel execution
                     ));

one more example (create a String from List<String>):

List<String> list = ...
String str = list.stream()
                 .collect(Collector.of(
                    StringBuilder::new,
                    StringBuilder::append,
                    StringBuilder::append,
                    StringBuilder::toString //last action of the accumulator (optional)  
                 ));

Looks nice, but compiler complaints: error: incompatible thrown types JSONException in method reference .collect(Collector.of(JSONArray::new, JSONArray::put, JSONArray::put)

I checked this on jdk 13.0.1 and JSON 20190722 and didn't find problems except of Expected 3 arguments, but found 1 in .collect(...).

(Gradle : implementation group: 'org.json', name: 'json', version: '20190722')


Fix:

public static JSONArray arrayToJson(double[] array) throws JSONException {
    return Arrays.stream(array).collect(
            JSONArray::new,
            JSONArray::put,
            (ja1, ja2) -> {
                for (final Object o : ja2) {
                    ja1.put(o);
                }
            }
    );
}

Note: The combiner cannot be a method reference to just JSONArray::put because this will just put one array into the other (e.g. [[]]) instead of actually combining them as is the desired behavior.

like image 164
kozmo Avatar answered Oct 12 '22 08:10

kozmo