I'm rather new to Java and to algorithms in general. I implemented the so called Two-pass algorithm, and want to know if there are improvements to my way of implementing it. What it does is it takes a matrix of ones and zeros and replaces all ones by labels. All ones that are connected should be labeled with the same label. Each such component should have a unique label. The end result can be visualized by replacing each label with a color, like this:I followed as closely as I could the pseudo-code available in this section of the Wikipedia article. But are there improvements?import java.util.ArrayList;import java.util.HashSet;import java.util.Set;public class MatrixComponents {    public int[][] labeledMatrix;    public MatrixComponents(int[][] matrix) {        ArrayList<ArrayList<Integer>> linked = new ArrayList<ArrayList<Integer>>();        int[][] labels = new int[matrix.length][matrix[0].length];        int NextLabel = 0;        //First pass        for(int i=0; i<matrix.length; i++) {            for( int j=0; j<matrix.length; j++) {                labels[i][j] = 0;            }        }        for(int i=0; i<matrix.length; i++) {            for(int j=0; j<matrix[0].length; j++) {                if(matrix[i][j] != 0) {                    //Labels of neighbors                    ArrayList<Integer> neighbors = new ArrayList<Integer>();                    for(int ni=-1; ni<=1; ni++) {                        for(int nj=-1; nj<=1; nj++) {                            if(i+ni<0 || j+nj<0 || i+ni>labels.length-1 || j+nj>labels[0].length-1) {                                continue;                            }                            else {                                if(i+ni == 0 && i+nj == 0) continue;                                if(labels[i+ni][j+nj] != 0) neighbors.add(labels[i+ni][j+nj]);                            }                        }                    }                    if(neighbors.size() == 0) {                        ArrayList<Integer> tempArrayList = new ArrayList<Integer>();                        tempArrayList.add(NextLabel);                        linked.add(NextLabel, tempArrayList);                        labels[i][j] = NextLabel;                        NextLabel++;                    }                    else {                        labels[i][j]=1000*1000;                        for(int neighbor : neighbors) {                            if(neighbor < labels[i][j]) labels[i][j] = neighbor;                        }                        for(int neighbor : neighbors) {                            linked.set(neighbor,union(linked.get(neighbor),neighbors));                        }                    }                }            }        }        //Second pass        for(int i=0; i<matrix.length; i++) {            for(int j=0; j<matrix[0].length; j++) {                ArrayList<Integer> EquivalentLabels = linked.get(labels[i][j]);                labels[i][j]=1000*1000;                for(int label : EquivalentLabels) {                    if(label < labels[i][j]) labels[i][j]=label;                }            }        }        labeledMatrix = labels;    }    //union: http://stackoverflow.com/questions/5283047/intersection-and-union-of-arraylists-in-java    public <T> ArrayList<T> union(ArrayList<T> list1, ArrayList<T> list2) {        Set<T> set = new HashSet<T>();        set.addAll(list1);        set.addAll(list2);        return new ArrayList<T>(set);    }    public int[][] getLabeledMatrix() {        return labeledMatrix;    }    public static void main(String[] args) {        int[][] matrix = {{0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,                0, 0, 0, 0, 0, 0, 0}, {1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0,                1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1}, {0, 1, 0, 0, 0, 0, 0,                1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                0}, {0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,                0, 1, 0, 0, 1, 0, 0, 1, 0}, {0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0,                1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1}, {0, 0, 0, 0, 1,                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0,                0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0,                0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0,                0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1}, {0, 1, 0, 0,                1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,                0, 0, 1, 0}, {0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,                0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}, {1, 1, 1, 0, 1, 1, 0, 1, 1, 1,                1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1}, {0, 0,                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,                1, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0,                0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, {1, 1, 0, 0, 1, 1, 0, 1, 0,                0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1}, {0,                0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1,                0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,                0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 0, 0,                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1,                0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,                0, 1, 0, 0, 1, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,                1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, {0, 1, 1, 0, 1,                1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1,                1, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,                0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,                0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 1,                1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1,                1, 1, 1, 1}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,                0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 1, 0, 0,                1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 1,                1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0,                1, 1, 1, 1, 1}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,                0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0,                0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}, {1,                1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1,                0, 1, 1, 0, 1, 1, 0}, {0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};        MatrixComponents matrixComponents = new MatrixComponents(matrix);        int[][] newMatrix = matrixComponents.getLabeledMatrix();        System.out.println({);        for(int i=0; i<newMatrix.length; i++) {            System.out.print({);            for(int j=0; j<newMatrix[0].length; j++) {                if(j != newMatrix[0].length-1)                    System.out.print(newMatrix[i][j]+, );                else                    System.out.print(newMatrix[i][j]);            }            if(i != newMatrix.length-1)                System.out.println(},);            else                System.out.println(});        }        System.out.print(});    }}The test in the main method prints the array. I don't know of any quick way of visualizing it in Java, but if it would be visualized it would look like my image above.
Two-pass algorithm implementation in Java
java;algorithm;beginner;matrix
Declare by interface and not implementationInstead ofArrayList<ArrayList<Integer>> linked = new ArrayList<ArrayList<Integer>>();use:List<List<Integer>> linked = new ArrayList<List<Integer>>();Or, if you're using Java 7+:List<List<Integer>> linked = new ArrayList<>();Edit: When looking at your code a bit more, with all the union method and stuff going on, I wonder if it perhaps should be List<Set<Integer>> right from the start, so that you could uselinked.get(neighbor).addAll(neighbors);instead of what you currently do:linked.set(neighbor,union(linked.get(neighbor),neighbors));Algorithmically speaking, this part://First passfor(int i=0; i<matrix.length; i++) {    for( int j=0; j<matrix.length; j++) {        labels[i][j] = 0;    }}Is a) Not part of the first pass. b) Totally unnecessary as the labels array is filled with zeros already. c) Buggy if matrix is not square.int[][] matrix = {{0, 0, 0, 0, 1, ...I'd highly recommend reading from a file instead of hardcoding into the code!Your constructor and your main method is doing way too many things, break up the code into additional methods.Some methods can include:Read matrix from file / some input / codeOne (or more) methods for doing the first pass (you can put the 2d outer loop in one method, which can call another method)One method for the second passOne method for the outputpublic int[][] labeledMatrix;Don't use public fields like that, that one should be private. It's good to restrict the visibility as much as possible.i and j vs. x and ySometimes 2d arrays are indexed as matrix[x][y] and sometimes as matrix[y][x], to make it clear which version you're using, don't use i and j. I really don't like those variable names when using 2d arrays.It is a good practice to always use braces, even for one-liners: (Even I get told this from time to time!)if(i+ni == 0 && i+nj == 0) continue;if(labels[i+ni][j+nj] != 0) neighbors.add(labels[i+ni][j+nj]);Is changed to:if (i + ni == 0 && i + nj == 0) {    continue;}if (labels[i + ni][j + nj] != 0) {    neighbors.add(labels[i + ni][j + nj]);}Remember the comments about the naming though.For your drawing an image plans, you should read up on Creating and Drawing to an Image and the chapter that follows it Writing/Saving an Image. You can use the Graphics2D object as shown in the first link to draw rectangles on the image.if(neighbors.size() == 0) {is the same asif (neighbors.isEmpty()) {