The specific error you get is because Stream.min()
requires a parameter specifying how to order the elements of the stream. In this case, you want to order the DoubleProperty
by its wrapped double
value, so you can do
Optional<DoubleProperty> minX = rectangles.stream()
.map(Rectangle::xProperty)
.min(Comparator.comparing(Double::getValue));
(get a stream of the x properties, and then choose the one with the minimum value)
Equivalently:
Optional<DoubleProperty> minX = rectangles.stream()
.min(Comparator.comparing(Rectangle::getX))
.map(Rectangle::xProperty);
(choose the rectangle with the minimum x, and then get its x property).
Note, however, that these probably don't do what you want. The minimum x value will be found at the time that code is executed, and you get the DoubleProperty
that wraps that value. If another rectangle with a smaller x
value is added to the list, you still have a reference to the original DoubleProperty
; similarly if the x-value of the rectangle corresponding to the property you received is changed so it is no longer the minimum, then your property will no longer represent the minimum value.
I'm assuming that what you want is a value which can be observed (you can register listeners with it) and which updates if either the list changes or if the x
property of any rectangles in the list change.
You can create a binding that does this. You need to create an observable list with an extractor so that the binding can be invalidated when either the list changes, or the xProperty()
of any of the rectangles in the list change.
Then use Bindings.createDoubleBinding()
with a function that computes the minimum value and binds to the list:
public static void main(String[] args) {
Random rnd = new Random();
// create list with an extractor:
ObservableList<Rectangle> rectangles =
FXCollections.observableArrayList(rect -> new Observable[] { rect.xProperty()});
DoubleBinding minX = Bindings.createDoubleBinding(
() -> rectangles.stream()
.mapToDouble(Rectangle::getX)
.min()
.orElse(Double.POSITIVE_INFINITY),
rectangles
);
minX.addListener((obs, oldMin, newMin) -> System.out.println("Min X changed from "+oldMin+" to "+newMin));
for (int i = 0; i < 50; i++) {
rectangles.add(new Rectangle(rnd.nextDouble(), rnd.nextDouble(), 100, 100));
}
}
The DoubleBinding
will probably work for anything you need (like a DoubleProperty
it implements ObservableDoubleValue
, which provides almost all the API you are likely to need). It you specifically need a property, just do
DoubleProperty minXProperty = new SimpleDoubleProperty();
minXProperty.bind(minX);