NateH06
NateH06

Reputation: 3594

Returning min on a stream determined by object outside of Stream

I'm looking for a Comparator to write to put inside a min in a stream on a collection, let's just say it's a List<Node> . Normally I'd just compare the objects of the List against one another, but my issue is I have a <Node> which is outside of the collection, and I need to return the minimum value of the Nodes within the collection, as they are pitted against the parent node.

I have an object of Node

public class Node {
  private int cost;
  private int location;
  public int getCost() { return cost }
}

I compare the nodes in the collection against the parent node with an outside function:

public int distanceBetween(Node parent, Node child) { ... }

And now I want to basically write a stream operation that returns the Node with the lowest value as it compares to its parent Node but that won't be in the set. Something like:

private Node returnOpenNodeWithLowestFCost(Node parent) {
      return nodeList.stream()
                     .min( (n1 , n2) -> ???);
                     .getOrElse(parent); 
  }

nodeList does not contain parent, and is a List<Node>

In the area containing the ??? is where I would send each N out for evaluation against its parent. So, if calling

distanceBetween(parent, n1) > distanceBetween(parent, n2) , it would result in n1 being returned . But I can't quite configure the function correctly. Any ideas? Thank you!

Upvotes: 3

Views: 156

Answers (2)

Misha
Misha

Reputation: 28153

You can use Comparator.comparingInt to make the comparator:

Comparator<Node> byDistFromParent = Comparator.comparingInt(n -> distanceBetween(parent, n));

It is customary to use static import of comparingInt, so you stream expression becomes:

return nodeList.stream()
          .min(comparingInt(n -> distanceBetween(parent, n));
          .orElse(parent); 

Upvotes: 5

fps
fps

Reputation: 34460

The parent node (the one which is not contained in the list) seems to be fixed. This establishes an origin from which to measure the distance to the nodes of the list. If I understand correctly, you want to return the node of the list which is nearest this parent node.

For this, you'd need to get the distances of nodes n1 and n2 to the parent node, and compare these actual distances each other. You should return a negative value if n1 is closer to the parent node than n2, 0 if both n1 and n2 are equally far away from the parent node, and a positive value if n2 is closer to the parent node than n1. Here is a method with that logic:

private int compareDistances(Node n1, Node n2) {
    int distance1 = this.distanceBetween(parent, n1);
    int distance2 = this.distanceBetween(parent, n2);

    return distance2 - distance1; // negative if n1 closer than n2
}

And here's the comparator that uses the method above:

return nodeList.stream()
    .min(this::compareDistances)
    .getOrElse(parent); 

Note: if you wanted exactly the opposite (to return the node that is farthest the parent node instead of the one that is nearest the parent node), you should use max instead of min:

return nodeList.stream()
    .max(this::compareDistances)
    .getOrElse(parent); 

Upvotes: 3

Related Questions