I'm creating a class to describe a zigzag line fit to a set of data. It implements my interface Fittable, which just contains evaluate() (I have mulitple kinds of curves that all implement this interface). I created the private inner class Node to describe a vertex. It will give the slope going to the left and the slope to the right.I'm doing a double-check in evaluate(). I am determining the value based off both the floor() and ceiling() values. However, sometimes I get values that don't match up and the IllegalStateException is being thrown. This is because the values for the slopes aren't the same, which lends me to believe that there's a problem with my while loop in the constructor, but I need a fresh set of eyes.Of course, optimizations are always welcome.import java.util.Comparator;import java.util.Iterator;import java.util.NoSuchElementException;import java.util.TreeSet;/** * * @author gobernador */public class LinearizedFit implements Fittable {    private TreeSet<Node> data;    public LinearizedFit(double[][] input) throws IllegalArgumentException {        for (int r = 0; r < input.length; r++) {            if (input[r].length != 2) {                throw new IllegalArgumentException(Data must be in a smooth, two-column format.);            }        }        data = new TreeSet(new NodeComparator());        for (double[] coords : input) {            data.add(new Node(coords[0], coords[1]));        }        Iterator<Node> iter = data.iterator();        Node last, node = null, next = iter.next();        while (true) {            last = node;            node = next;            try {                next = iter.next();                node.slopeRight = slope(node, next);            } catch (NoSuchElementException ex) {                next.slopeLeft = slope(last, node);                next.slopeRight = slope(last, node);                break;            }            if (last != null) {                node.slopeLeft = slope(last, node);            } else {                node.slopeLeft = slope(node, next);            }        }    }    public double evaluate(final double x) {        Node thisNode = new Node(x);        Node floor = data.floor(thisNode);        Node ceiling = data.ceiling(thisNode);        double d1, d2;        try {            d1 = floor.y + (floor.slopeRight * (x - floor.x));        } catch (NullPointerException e) {            return ceiling.y + (ceiling.slopeLeft * (x - ceiling.x));        }        try {            d2 = ceiling.y + (ceiling.slopeLeft * (x - ceiling.x));        } catch (NullPointerException e) {            return d1;        }        if (d1 != d2) {            throw new IllegalStateException(Bad information);        }        return d1;    }    private double slope(final Node n1, final Node n2) {        return (n2.y - n1.y) / (n2.x - n1.x);    }    private class Node {        final double x;        final double y;        double slopeLeft;        double slopeRight;        Node(double x, double y) {            this.x = x;            this.y = y;        }        Node(double x) {            this(x, 0);        }    }    private class NodeComparator implements Comparator<Node> {        public int compare(final Node o1, final Node o2) {            if (o1.x < o2.x) {                return -1;            }            if (o1.x > o2.x) {                return 1;            }            return 0;        }    }    public static void main(String... args) {        LinearizedFit lf = new LinearizedFit(new double[][]{{1, 1}, {0, 0}, {2, 0}});        System.out.println(lf.evaluate(-1));        System.out.println(lf.evaluate(0.5));        System.out.println(lf.evaluate(1.5));        System.out.println(lf.evaluate(3));    }}EDIT: added a main methodI expect with this main method to get an output-1.0  0.5  0.5  -1.0  but instead I get-1.0  0.5  Exception in thread main java.lang.IllegalStateException: Bad information      at mypackage.LinearizedFit.evaluate(LinearizedFit.java:70)      at mypackage.LinearizedFit.main(LinearizedFit.java:113)  Java Result: 1Edit: SOLVED: the class below represents the working versionimport java.util.Comparator;import java.util.Iterator;import java.util.NoSuchElementException;import java.util.TreeSet;/** * * @author gobernador */public class LinearizedFit implements Fittable {    private TreeSet<Node> data;    public LinearizedFit(double[][] input) throws IllegalArgumentException {        for (int r = 0; r < input.length; r++) {            if (input[r].length != 2) {                throw new IllegalArgumentException(Data must be in a smooth, two-column format.);            }            data.add(new Node(input[r][0], input[r][1]));        }        Iterator<Node> iter = data.iterator();        Node last, node = null, next = iter.next();        do {            last = node;            node = next;            next = iter.next();            node.slopeRight = slope(node, next);            if (last != null) {                node.slopeLeft = slope(last, node);            } else {                node.slopeLeft = slope(node, next);            }        } while (iter.hasNext());        next.slopeLeft = slope(node, next);        next.slopeRight = slope(node, next);    }    public double evaluate(final double x) {        Node thisNode = new Node(x);        Node floor = data.floor(thisNode);        Node ceiling = data.ceiling(thisNode);        double d1, d2;        if (floor != null) {            d1 = floor.y + (floor.slopeRight * (x - floor.x));        } else {            return ceiling.y + (ceiling.slopeLeft * (x - ceiling.x));        }        if (ceiling != null) {            d2 = ceiling.y + (ceiling.slopeLeft * (x - ceiling.x));        } else {            return d1;        }        if (d1 != d2) {            throw new IllegalStateException(Bad information);        }        return d1;    }    private double slope(final Node n1, final Node n2) {        return (n2.y - n1.y) / (n2.x - n1.x);    }    private static class Node {        final double x;        final double y;        double slopeLeft;        double slopeRight;        Node(double x, double y) {            this.x = x;            this.y = y;        }        Node(double x) {            this(x, 0);        }    }    private static class NodeComparator implements Comparator<Node> {        public int compare(final Node o1, final Node o2) {            if (o1.x < o2.x) {                return -1;            }            if (o1.x > o2.x) {                return 1;            }            return 0;        }    }    public static void main(String... args) {        LinearizedFit lf = new LinearizedFit(new double[][]{{1, 1}, {0, 0}, {2, 0}});        System.out.println(lf.evaluate(-1));        System.out.println(lf.evaluate(0.5));        System.out.println(lf.evaluate(1.5));        System.out.println(lf.evaluate(3));    }}
Linearized Fit to Data
java
First, don't catch NullPointerExceptions. Not only is it slightly more inefficient, it's a terrible code smell. Instead, do this:if(floor != null){    d1 = floor.y + (floor.slopeRight * (x - floor.x));} else {    return ceiling.y + (ceiling.slopeLeft * (x - ceiling.x));}Second, if your nested classes don't need access to the outer class, go ahead and make it a static nested class. Just add the static modifier.private static class NodeComparator implements Comparator<Node> {Third, You loop over the data twice at the beginning. Once to verify integrity and another to add it to your tree. Why not combine the two?data = new TreeSet(new NodeComparator());for (double[] coords : input) {    if (coords.length != 2) {        throw new IllegalArgumentException(Data must be in a smooth, two-column format.);    }    data.add(new Node(coords[0], coords[1]));}Finally, using an exception to detect the end of the set makes me nervous. I would rewrite that using iter.hasNext().if(iter.hasNext()){    next = iter.next();    node.slopeRight = slope(node, next);} else {    next.slopeLeft = slope(last, node);    next.slopeRight = slope(last, node);    break;}