问题
Suppose I have a class Point
and a function to process Point
instances
class Point { private final int x, y; ... } ... void handlePoints(Iterable<Point> points) { for (Point p: points) {...} }
Now I would like to read points
from a file. Each line of the file contains two numbers, so I have a function ("factory method") to create a point
from a line.
Point makePoint(String line) { ... }
What should I do now? I can write a function to read the file to a list of points
and call the handlePoints
function.
List<Point> readPoints(BufferedReader reader) {...} // use makePoint here void handlePoints(BufferedReader reader) { List<Point> points = readPoints(reader); handlePoints(points); }
Unfortunately this function does not seem particularly elegant since it creates an unnecessary list of points in memory.
Wouldn't it be better to use iterators ?
void handlePoints(Iterator<Point> points) {...} Iterator<Point> readPoints(BufferedReader reader) {...} // use makePoint here void handlePoints(BufferedReader reader) { Iterator<Point> points = readPoints(reader); handlePoints(points); }
Does it make sense? Won't be this code too "noisy" in Java?
回答1:
If you don't need to have all points in memory, think of something more along these lines:
while (reader.ready())
{
String line = reader.readLine();
Point point = makePoint(line);
handlePoint(point);
}
How to do this with an iterator and handlePoints: (code for handling exceptions to be added)
class PointIterator implements Iterator<Point>
{
BufferedReader reader;
PointIterator(BufferedReader myReader) { reader = myReader; };
@Override
public boolean hasNext() { return myReader.ready(); };
@Override
public Point next() { return makePoint(myReader.readLine()); };
@Override
public void remove()
{ throw new UnsupportedOperationException("Remove not supported!"); };
}
And because handlePoints
takes an Iterable
:
class PointIterable implements Iterable<Point>
{
BufferedReader reader;
public PointIterable(BufferedReader myReader) { reader = myReader; };
@Override
public Iterator<Point> iterator() { return new PointIterator(reader); }
}
To use:
handlePoints(new PointIterable(reader));
回答2:
From a memory point of view, you won't really save any memory by using iterators - I'm guessing you'll be reading all the points into memory, so they'll all have to be stored somehow.
An iterator isn't a different collection type: it is simply a different way of iterating through a collection. For example, you could go list.iterator()
to get an iterator to loop through your list (or any collection).
The choice of what collection to use to hold all the points in memory is the one that will affect memory (eg. ArrayList
vs. LinkedList
).
回答3:
Just read once from file and have it in memory instead of reading every time from file
List<Points> points ;
public List<Point> readPoints(BufferedReader reader) {
if(points == null) {
points = new ArrayList();
// read from file and populate
points.add(point) ;
}
return points;
}
来源:https://stackoverflow.com/questions/14109926/iterators-to-read-and-process-file-in-java