Calculate the Sum Without Highest and Lowest Number in Java


The challenge

Sum all the numbers of the array except the highest and the lowest element (the value, not the index!).
(The highest/lowest element is respectively only one element at each edge, even if there are more than one with the same value!)

Example:

{ 6, 2, 1, 8, 10 } => 16
{ 1, 1, 11, 2, 3 } => 6

If array is empty, null or None, or if only 1 Element exists, return 0.

The solution in Java code

Option 1 (first pass):

public class Solution {
  public static int sum(int[] numbers) {
    // catch some edge cases
    if (numbers==null || numbers.length<3) return 0;

    // sort the array
    java.util.Arrays.sort(numbers);

    // sum up elements excluding the first and last
    int sum = 0;
    for(int i=1;i<numbers.length-1;i++) {
      sum += numbers[i];
    }
    return sum;
  }
}

Option 2 (using IntStream):

import static java.util.stream.IntStream.of;

public class Solution {
  public static int sum(int[] numbers) {
    return (numbers == null || numbers.length <= 2) ? 0 : of(numbers).sum() - of(numbers).max().getAsInt() - of(numbers).min().getAsInt();
  }
}

Option 3 (using streams):

import java.util.Arrays;

public class Solution {
  public static int sum(int[] numbers) {
    if(numbers == null || numbers.length < 2) return 0;
    Arrays.sort(numbers);
    return Arrays.stream(numbers).skip(1).limit(numbers.length-2).sum();
  }
}

Test cases to validate our code solution

import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.runners.JUnit4;

public class SolutionTest {
    @Test
    public void BasicTests() {
      assertEquals(16, Solution.sum(new int[] { 6, 2, 1, 8, 10}));     
    }
}

More extensive test cases to catch edge-cases

import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.runners.JUnit4;
import java.util.*;

public class SolutionTest {
    @Test
    public void SumOnlyOneElement() {
      assertEquals(0, Solution.sum(new int[] { 6 }));     
    }
    
    @Test
    public void SumOnlyTwoElements() {
      assertEquals(0, Solution.sum(new int[] { 6, 7 }));     
    }
    
    @Test
    public void SumPositives() {
      assertEquals(16, Solution.sum(new int[] { 6, 2, 1, 8, 10 }));     
    }
    
    @Test
    public void SumPositivesWithDoubleMax() {
      assertEquals(17, Solution.sum(new int[] { 6, 0, 1, 10, 10 }));     
    }
    
    @Test
    public void SumNegatives() {
      assertEquals(-28, Solution.sum(new int[] { -6, -20, -1, -10, -12}));     
    }
    
    @Test
    public void SumMixed() {
      assertEquals(3, Solution.sum(new int[] { -6, 20, -1, 10, -12}));     
    }
    
    @Test
    public void SumEmptyArray() {
      assertEquals(0, Solution.sum(new int[0]));     
    }
    
    @Test
    public void SumNullArray() {
      assertEquals(0, Solution.sum(null));     
    }
    
    @Test
    public void SumRandom() {
      for(int r=0; r<20;r++)
      {
        int[] numbers = new int[6];
        for(int i=0; i< numbers.length; i++)
        {
          numbers[i] = (int)Math.floor(Math.random() * 1100 - 500);
        }
        
        int sum = 0;
        for(int i = 0 ; i < numbers.length; i++) {
          sum += numbers[i];
        }
        
        int min = Arrays.stream(numbers).min().getAsInt();
        int max = Arrays.stream(numbers).max().getAsInt();
        
        int expected = sum - min - max;
        
        assertEquals(expected, Solution.sum(numbers));     
      }
    }
}