Determining if a given square is a magic square I'm writing the following program for a school assignment. The prompt is as follows:


  A magic square is square grid filled with distinct positive integers such that each cell contains a different integer and the sum of the integers in each row, column and diagonal is equal.


My task is to make a boolean method, named magical() that is passed a 2d array, and will return true if those criteria are met. This is the code I wrote:

private static boolean magical(int[][] square) {
        int length = square.length;
        //This loop checks for duplicate values
        for (int i = 0; i &lt; length; i++){
            for (int j = 0; j &lt; length; j++){
                int x = square[i][j];
                for (int a = 0; a &lt; length; a++){
                    for (int b = 0; b &lt; length; b++){
                        if (a == i &amp;&amp; b == j) continue;
                        if (x == square[a][b]) return false;
                    }
                }
            }
        }
        ArrayList&lt;Integer&gt; sums = new ArrayList&lt;&gt;();
        //This loop finds the sums of the rows and columns
        for (int i = 0; i &lt; length; i++){
            int sum = 0;
            int sum2 = 0;
            for (int j = 0; j &lt; length; j++){
                sum += square[i][j];
                sum2 += square[j][i];
            }
            sums.add(sum);
            sums.add(sum2);
        }
        //The next two loops find the sums of each diagonal. 
        int x = 0;
        int y = 0;
        int sum = 0;
        while (x &lt; length &amp;&amp; y &lt; length){
            sum += square[x][y];
            x++;
            y++;
        }
        sums.add(sum);
        sum = 0;
        x = 0;
        y = length - 1;
        while (x &lt; length &amp;&amp; y &gt;= 0){
            sum += square[x][y];
            x++;
            y--;
        }
        sums.add(sum);
        return sums.stream().allMatch(s -&gt; s.equals(sums.get(0)));
    }


Here are my questions:


Is there any way to confirm that there are no duplicate values in the array without having to nest four for loops? This seems like an incredibly inefficient system.
Is there any way to combine the two loops in the end that are used to make sure that the sum of values in each diagonal are the same? I am currently using two loops, but seeing as I am iterating through the same array, it seems inefficient to do it twice.


I am also open to any other suggestions you may have. Please note, it is given in the prompt that all arrays passed as parameters will be squares, and it is not required to test for this.
Answering your first question, yes there is a better way. Efficiency doesn't matter in your case but in this instance the more efficient thing is also easier on the eyes.

The usual idea would be to make a hash set of the elements, then you have O(1) look up of whether you have already inserted an elements, making the task O(n^2).

I'm not that familiar with Java sadly so to answer your second question I just propose the fairly imperative thing of doing everything in one traversal (I think probably it can be done with the functional constructs that Java has), like so.

private static boolean magical(int[][] square) {
    Set&lt;Integer&gt; seenInts = new HashSet&lt;&gt;();
    var leftDiagonalSum = 0;
    var rightDiagonalSum = 0;
    var rowSums = new int[square.length];
    var colSums = new int[square.length];

    for(var i = 0; i &lt; square.length; i++) {
        for(var j = 0; j &lt; square.length; j++) {
            var currentElement = square[i][j];

            seenInts.add(currentElement);
            leftDiagonalSum += (i == j) ? currentElement : 0;
            rightDiagonalSum += (i == square.length - 1 - j) ? currentElement : 0;
            rowSums[i] += currentElement;
            colSums[j] += currentElement;
        }
    }

    Set&lt;Integer&gt; sumSet = new HashSet&lt;&gt;();

    sumSet.add(leftDiagonalSum);
    sumSet.add(rightDiagonalSum);

    for(var i = 0; i &lt; square.length; i++) {
        sumSet.add(rowSums[i]);
        sumSet.add(colSums[i]);
    }

    var noDuplicates = seenInts.size() == square.length * square.length;
    var allSameSums = sumSet.size() == 1;

    return noDuplicates &amp;&amp; allSameSums;
}


Edit - While I may not know much Java, there's no reason to specify the implementation of Set used, so the type of seenInts and sumSet can just be Set