Home > Enterprise >  Subtracting between two ArrayList in Java
Subtracting between two ArrayList in Java

Time:11-27

Is there any fast function to do the following code?

ArrayList<Double> A = new ArrayList<>();
ArrayList<Double> B = new ArrayList<>();
//ignore adding steps
// A = [1,2,3,4,5]
// B = [0,1,2,3,4]
C = A - B
// get C = [1,1,1,1,1]

CodePudding user response:

TL;DR: Refer to the two complete code examples below, and their section's headings for context.

Approaches

Imperative approach

Imperative programming is commonly described as "instructing the individual steps to achieve a certain goal".

We can use for-loops—a language feature associated with imperative programming—to iterate through the lists A and B, and to collect the differences of their elements in the list C:

import java.util.ArrayList;
import java.util.Arrays;

public class ImperativeApproach {
  public static void main(String[] args) {
    ArrayList<Double> A = new ArrayList<>(Arrays.asList(new Double[] {1d,2d,3d,4d,5d}));
    ArrayList<Double> B = new ArrayList<>(Arrays.asList(new Double[] {0d,1d,2d,3d,4d}));
    
    ArrayList<Double> C = new ArrayList<>();
    
    assert A.size() == B.size();
    int size = A.size();
    for (int i = 0; i < size;   i) {
      C.add(A.get(i) - B.get(i));
    }
    
    System.out.println(C); // [1.0, 1.0, 1.0, 1.0, 1.0]
  }
}

Functional approach

Functional programming is more declarative than imperative programming: It can be described as "requesting a certain outcome under following certain steps".

Characteristics of functional programming usually include higher-order functions and functions as first-class citizens, function composition, lambdas, and more.

Aside: Note that both imperative and functional programming are just paradigms; ways of classifying code or languages by certain "traits". Example: With the addition of Streams (see below) to Java, it has become easier to write functional code in Java.

As mentioned before, we can make use of Java Streams. Example:

  1. Create a stream of indices we want to access A/B at; namely, 0 to size of A or B.
  2. Map the indices to the differences of the elements of A and B.
  3. Collect the (streamed) result as a list named C.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.IntStream;

public class FunctionalApproach {
  public static void main(String[] args) {
    ArrayList<Double> A = new ArrayList<>(Arrays.asList(new Double[] {1d,2d,3d,4d,5d}));
    ArrayList<Double> B = new ArrayList<>(Arrays.asList(new Double[] {0d,1d,2d,3d,4d}));
    
    assert A.size() == B.size();
    int size = A.size();
    Double[] arrayC = IntStream.range(0, size)
        .mapToDouble((index) -> A.get(index) - B.get(index))
        .boxed()
        .toArray(Double[]::new);
    
    ArrayList<Double> C = new ArrayList<>(Arrays.asList(arrayC));
    
    System.out.println(C); // [1.0, 1.0, 1.0, 1.0, 1.0]
  }
}

(@GrzegorzPiwowarek provided alternative and arguably better implementations on a similar but older question.)

Addendum

There may have been unfamiliar expressions in the examples above, which I'll try to explain in this section.

Assertions

Assertions in Java are a development tool to ensure correct functionality of your code. If assertions fail, they will throw an exception. They will only run if you correctly compile and enable them.

Note that assertions do not replace proper checking! Oracle has a summary of when to use assertions.

In the examples above I use assertions mainly to semantically describe that (roughly) "the following code only works under the assertion's condition".

Primitives and boxed values

(Auto-)boxing in Java refers to converting a primitive value to its corresponding wrapper class.

This is required in places where primitives cannot be used, or rather where Objects are expected. Examples are Generics like List, for which you'll find simple explanations in Oracle's autoboxing tutorial.

Be extra careful if—in your code—references to such wrapper classes can be null: Java cannot unbox null to a primitive, instead it will throw a runtime exception! In the above code, no such scenario can occur.

In both approaches

Since arrays are more readable and statically compile, I chose to provide the lists' initial values as arrays. My implementation came with the following requirements:

  1. Constructing ArrayList with initial values requires a Collection.[1]
  2. Arrays.asList() returns a Collection, but requires a non-primitive array (here: array of boxed values; further: boxed array).[2]
  3. Initializing a boxed array (Double[]) requires the elements to be of the corresponding primitive type; we need to provide the numbers in type double.[3]
  4. Declaring number literals as double requires us to suffix them with d (or use a decimal point).[4]

This means that this invalid code:

ArrayList<double> A = new double[]{1, 2, 3, 4, 5};

Needs to be written e.g. as follows to be valid:

ArrayList<Double> A = new ArrayList<>(Arrays.asList(new Double[]{1d, 2d, 3d, 4d, 5d}));

In the imperative approach

No further code changes are required in the imperative approach's example. Adding numbers to the list C autoboxes the numbers, because here no intermediate object with certain restrictions like new Double[] is used.

In the functional approach

In the Streams example, IntStream.mapToDouble() returns a DoubleStream (a stream acting on primitives). Its toArray() function would return a primitive array (double[]), which we cannot easily provide to the construction of the list C as mentioned before.

Therefore we first need to box it (see DoubleStream.boxed()), which returns a Stream<Double>. This stream's elements can then be collected in a boxed array (by providing the array's constructor, Double[]::new; see Oracle's tutorial "Method References").

Such an array can then be used to construct a list as discussed before.

CodePudding user response:

You have to loop through each element of both the array and subtract it from the subordinates in the other array please find the working code snippet below.

import java.util.*;
class HelloWorld {
    public static void main(String[] args) {
       int[] list1 = {1,2,3,4,5};
        int[] list2 = {0,1,2,3,4};
        int[] list3 = {0,0,0,0,0};
        
        for(int i =0; i< list1.length; i  )
        {
          list3[i] = list1[i] - list2[i];
        }
        
       for(int i =0; i< list3.length; i  )
       {
          System.out.print(list3[i]);
       }
        
    }
}

Which will give you the following output :

[1, 1, 1, 1, 1]

CodePudding user response:

You may want to check this old question and its first response which it recommends to use the Stream API. How to subtract values of two lists/arrays in Java?

  •  Tags:  
  • java
  • Related