So I have this piece of code which uses several maps to store some simple classes. Now I also want to look op some of the values based on for example the x position of this item. I tried to do something with Generics and lambda's, but it just didn't work out. Also if there is an easier way to do this, please tell. I have most of my experience in Python, so this might just not be practical in Java.
interface Compare {
public <T, P> boolean apply(T obj, P comp);
}
class Utils {
public static <T, P> List<T> retrieve(Collection<T> args, P value, Compare c) {
List<T> r = new ArrayList<T>();
for (T i: args) {
if (c.apply(i, value)) {
r.add(i);
}
}
return r;
}
}
class Point {
int x;
int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
This doesn't raise any errors as of yet, but when I try to actually use the retrieve function on a HashMap it doesn't work.
Point p = Utils.retrieve(points.values(), 0, (Point p, Integer x) -> {return px == x;});
There are two errors in eclipse:
How would one handle this situation? My thanks in advance.
You're fairly close to getting the code you're after.
Firstly, move the generic parameter declaration to the interface (as the esteemed Esquire Wasserman suggests in his comment).
interface Compare<T, P> {
public boolean apply(T obj, P comp);
}
Now you just need to modify the way you're calling your new toys. I've created a main method with the following code and it works nicely:
public static void main(String[] args) {
Set<Point> points = new HashSet<>(8);
points.add(new Point(0, 0));
points.add(new Point(1, -1));
points.add(new Point(1, 1));
points.add(new Point(-1, -1));
points.add(new Point(-1, -1));
System.out.println("Set<Point> points:\n" + points);
Compare<Point, Integer> sameX = (p, x) -> p.x == x;
List<Point> matchingPoints =
Utils.<Point, Integer>retrieve(points, 0, sameX);
System.out.println("\nmatchingPoints:\n" + matchingPoints);
}
I've used a simple Set<Point>
here because I don't know what you're intending to store in a Map
, but calling Map.values()
will produce a Collection<Point>
just as well as the Set<Point>
does in this example.
The reason this works is that you specify the parameter types to the generic static method in the angle-brackets immediately before the name of the static method: Utils.<Point, Integer>retrieve
and you don't put the types inside the lambda. It's also worth saying here that lambda expressions should be as compact as possible, so rather than {return px == x;}
you can simply have px == x
.
Note, however, that in order to see the output in a readable form, you need to override the toString()
method in your Point
class:
@Override
public String toString() {
return "Point(" + x + ", " + y + ")";
}
This will give you the following output:
Set<Point> points:
[Point(-1, -1), Point(0, 0), Point(1, -1), Point(-1, -1), Point(1, 1)]
matchingPoints:
[Point(0, 0)]
(Also note that you don't have to move the lambda out of the call to the retrieve
method, but it makes the code tidier, and fits better in this narrow Stack Overflow window.)
Your follow-up comment made me realise that your Utils.retrieve
method was going to hit trouble unless exactly the right sort of Compare
method was passed to it. Rather than leave things open to chance, it's better to lock this down by modifying the signature of your retrieve
method so that it becomes this:
public static <T, P> List<T> retrieve(Collection<T> args,
P value, Compare<T, P> c) {
Now the Compare
object which is passed to retrieve
must take the same types which apply to the Collection<T>
and the value
. Once you've made this change you can inline your lambda expression like this:
List<Point> matchingPoints = Utils.<Point, Integer>retrieve(
points, 0, (p, x) -> p.x == x);
You won't get errors now, because the strict type applied to the Compare
parameter in your retrieve
method allows the IDE (and compiler) to see that the lambda must be of type <Point, Integer>
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.