2
\$\begingroup\$

I'm scanning a CSV file to see which values fit inside of a given box. The CSV file has X and Y coordinates, and the arguments to the function are the perimeters of a box (i.e, top, bottom, left side, right side). I don't want to use any external libraries; part of the purpose of this is to learn how to speed up code manually.

I'm fairly new to Java, so any input would be helpful. I'm trying to get this down to 100ms if possible, but right now it's taking about 1000ms.

Scanner dataStream = new Scanner(fileMain);
while (dataStream.hasNext()){
    String data = dataStream.next();
    String[] values = data.split(",", 3);
    if(Double.parseDouble(values[0]) > lowX && Double.parseDouble(values[0]) < highX){ 
            if(Double.parseDouble(values[1]) < highY && Double.parseDouble(values[1]) > lowY){
                System.out.println(data);

    }

dataStream.close();

Data is formatted like so:

90.92, 102.3
40.28, 82.32
13.02, 80
72, 104.82
\$\endgroup\$
  • 2
    \$\begingroup\$ In two places in this code you parse the same value as a double twice. Parse it once and save it. \$\endgroup\$ – Keatinge May 16 '16 at 4:28
  • 3
    \$\begingroup\$ @Racialz Comments are for seeking clarification. Please write that as an answer, even if it is just that short. \$\endgroup\$ – 200_success May 16 '16 at 5:22
  • 3
    \$\begingroup\$ Welcome to Code Review! Do not vandalise your post, we are alerted to it in Charcoal HQ and have to clean it up. This may result in a question ban. see question bans \$\endgroup\$ – user90823 May 16 '16 at 6:16
  • \$\begingroup\$ How many lines are there? \$\endgroup\$ – abuzittin gillifirca May 16 '16 at 7:02
  • \$\begingroup\$ Can you supplement your question with the method declaration, so that we have a better sense of where the variables are coming from? \$\endgroup\$ – h.j.k. May 16 '16 at 13:57
2
\$\begingroup\$

First of all, note that you can always use Point2D.Double for representing points in a plane.

Next, I would split your program into two methods: the first one for pruning points that are not within a specified bounding box, and the second one for reading the points from the standard input, and putting them into the first one.

What comes to coding conventions, I would have a blank line before the if statement. Also, you should surround the condition of an if statement with a single space. So, instead of

String[] values = data.split(",", 3);
if(Double.parseDouble(values[0])){ ...

you should write

String[] values = data.split(",", 3);

if (Double.parseDouble(values[0])) { ...

All in all, I had this in mind:

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Scanner;

public class CoordinateUtilities {

    public static List<Point2D.Double> 
        getPointsWithinBoundingBox(final List<Point2D.Double> pointList,
                                   final double lowX,
                                   final double highX,
                                   final double lowY,
                                   final double highY) {
        Objects.requireNonNull(pointList, "The list of points is null.");
        checkXBounds(lowX, highX);
        checkYBounds(lowY, highY);
        final List<Point2D.Double> ret = new ArrayList<>(pointList.size());

        for (final Point2D.Double point : pointList) {
            final double x = point.x;
            final double y = point.y;

            if (lowX <= x && x <= highX && lowY <= y && y <= highY) {
                ret.add(point);
            }
        }

        return ret;
    }

    public static void main(final String... args) {
        final Scanner scanner = new Scanner(System.in);
        final double lowX  = 50.0; 
        final double highX = 100.0;
        final double lowY  = 30.0;
        final double highY = 60.0;

        final List<Point2D.Double> allPoints = new ArrayList<>();

        while (scanner.hasNextLine()) {
            final String line = scanner.nextLine();

            if (line.trim().equals("quit")) {
                break;
            }

            final Point2D.Double point = parsePoint(line);

            if (point != null) {
                allPoints.add(point);
            }
        }

        final List<Point2D.Double> boundedPoints = 
                getPointsWithinBoundingBox(allPoints, lowX, highX, lowY, highY);

        boundedPoints.forEach(System.out::println);
    }

    private static Point2D.Double parsePoint(final String line) {
        final String[] tokens = line.trim().split("\\s*,\\s*");

        if (tokens.length < 2) {
            return null;
        }

        try {
            final double x = Double.parseDouble(tokens[0]);
            final double y = Double.parseDouble(tokens[1]);
            return new Point2D.Double(x, y);
        } catch (final NumberFormatException ex) {
            return null;
        }
    }

    private static void checkXBounds(final double lowX, final double highX) {
        if (Double.isNaN(lowX)) {
            throw new IllegalArgumentException(
                    "The lower bound of the x-coordinate is NaN.");
        }

        if (Double.isNaN(highX)) {
            throw new IllegalArgumentException(
                    "The upper bound of the x-coordinate is NaN.");
        }

        if (lowX > highX) {
            throw new IllegalArgumentException(
                    "The lower bound of the x-coordinate (" + lowX + "is " +
                    "larger than the upper bound of the x-coordinate (" +
                    highX + ").");
        }
    }

    private static void checkYBounds(final double lowY, final double highY) {
        if (Double.isNaN(lowY)) {
            throw new IllegalArgumentException(
                    "The lower bound of the y-coordinate is NaN.");
        }

        if (Double.isNaN(highY)) {
            throw new IllegalArgumentException(
                    "The upper bound of the y-coordinate is NaN.");
        }

        if (lowY > highY) {
            throw new IllegalArgumentException(
                    "The lower bound of the y-coordinate (" + lowY + "is " +
                    "larger than the upper bound of the y-coordinate (" +
                    highY + ").");
        }
    }
}

Hope that helps.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.