There is a Set accepting in the constructor an array of Numbers and a summator method that adds all the numbers from the collection. I’m confused that the code for summation is repeated ... can it be somehow more beautiful to solve this problem ... perhaps with the help of generics? I tried to write generic code and parameterize the class, but in this form it also does not work

/* T sum = null; for (T element : setNumbers) sum += element; return sum; */ 

Or it is impossible in principle to use generics here? and you need to look for a beautiful solution in working with Collections or stream api, some lambda .... Prompt the direction at least. I bring my code ...

 private Set<Number> numbers; private Class type; public MathBox(Number[] numbers){ if (numbers[0] instanceof Integer) this.type = Integer.class; if (numbers[0] instanceof Long) this.type = Long.class; if (numbers[0] instanceof Double) this.type = Double.class; if (numbers[0] instanceof Float) this.type = Float.class; this.numbers = new HashSet(Arrays.asList(numbers)); } public Number summator() { if (type == Integer.class) { Integer sum = 0; for (Number element : numbers) sum += (Integer) element; return sum; } if (type == Long.class) { Long sum = 0L; for (Number element : numbers) sum += (Long) element; return sum; } if (type == Double.class) { Double sum = 0.0; for (Number element : numbers) sum += (Double) element; return sum; } if (type == Float.class) { Float sum = 0.0F; for (Number element : numbers) sum += (Float) element; return sum; } return null; } 
  • one
    Convert the collection into a set.stream (). ToIntStream (i -> i) stream and call the sum function .sum () - GenCloud
  • Yes, streaming is good, there will be fewer lines, probably ... but I have a little other request. Now, if it would be possible to transfer the data type (Integer, Double ...) to this stream. Or substitute it from the type variable into one universal code ... - VBugaenko

2 answers 2

Unfortunately, a sufficiently beautiful code will not work, due to the fact that the sum() method is not defined in the abstract class Number . It is defined only in some of the heirs ( Integer, Double ), so in your case it is impossible to do without caste and forcing what method to use.

You can use the Java Stream API to do this:

  import java.util.Arrays; public class MathBox<T extends Number> { private final T[] numbers; MathBox(T[] arr){ numbers = arr; } public int intSum(){ return Arrays.stream(numbers).mapToInt(x -> x.intValue()).sum(); } public double doubleSum(){ return Arrays.stream(numbers).mapToDouble(x -> x.doubleValue()).sum(); } public long longSum(){ return Arrays.stream(numbers).mapToLong(x -> x.longValue()).sum(); } } 

    I would try this:

      import java.util.Arrays; import java.util.HashSet; import java.util.Set; public class MathBox { private Set<Number> numbers; private Class type; public MathBox(Number... numbers) { this.numbers = new HashSet(Arrays.asList(numbers)); } public static void main(String[] args) { System.out.println(new MathBox(1, 2, 3).sum()); System.out.println(new MathBox(1.1, 2.2, 3.3).sum()); } public Number sum() { Double sum = 0.0; for (Number element : numbers) sum += Double.valueOf(String.valueOf(element)); return sum; } } 

    If the type of result is not very important.

    UPD: Either way, it is more correct:

      import java.util.logging.Logger; interface MathBox<T> { T sum(); } public class MathBox2 { private static final Logger LOG = Logger.getLogger(MathBox2.class.getName()); public static void main(String[] args) { MathBox mathBox = new IntegerMathBox(1, 2, 3); System.out.println(mathBox.sum()); mathBox = new DoubleMathBox(1.1, 2.1, 3.1); System.out.println(mathBox.sum()); } } class IntegerMathBox implements MathBox<Integer> { private Integer[] array; public IntegerMathBox(Integer... array) { this.array = array; } @Override public Integer sum() { Integer integer = 0; for (Integer i : array) { integer += i; } return integer; } } class DoubleMathBox implements MathBox<Double> { private Double[] array; public DoubleMathBox(Double... array) { this.array = array; } @Override public Double sum() { Double d = 0.0; for (Double dd : array) { d += dd; } return d; } } 
    • an interesting solution (turn into a string, and then into a Double) ... but it looks like a crutch))), then you still need something else - VBugaenko
    • Added option) - ezhov_da