Need a function that calculates mines and max from Stream
public static & lt; t & gt; Void FindminMax (
Stream & lt;? EXTENDS T & GT; Stream,
Comparator & lt;? Super T & GT; order)
because LStream allows for only one terminal operation call, it is not possible:
optional & lt;? EXTENDS T & GT; min = stream.min (Order);
Optional & lt;? EXTENDS T & GT; Max = Stream.max (Order);
Is it possible to somehow “split” streams so that the operation over 1 does not affect the 2nd?
object [] mass = new object [2];
Mass [0] = Stream;
Mass [1] = stream;
Stream & lt;? EXTENDS T & GT; STR1 = (STREAM & LT ;? Extends T & GT;) Mass [0];
Stream & lt;? EXTENDS T & GT; STR2 = (STREAM & LT ;? Extends T & GT;) Mass [1];
Optional & lt;? EXTENDS T & GT; min = STR1.min (Order);
Optional & lt;? EXTENDS T & GT; Max = Str2.max (Order);
So also flies the exception.
Suppose I made a stream from elements from 1 … 10
stream & lt; integer & gt; STR = Stream. & lt; integer & gt; iTerate (1, n- & gt; n + 1)
.limit (10);
and a comparator Comparator & lt; Integer & gt; COMP = (Integer O1, Integer O2) - & gt; O1.comPare (O1, O2);
Pass it in the method:
public static & lt; t & gt; Void FindminMax (
Stream & lt;? EXTENDS T & GT; Stream,
Comparator & lt;? Super T & GT; order)
{
Object [] Mass = New Object [2];
Stream str = stream;
MASS [0] = NULL; // Max
Mass [1] = NULL; // MIN.
If (Stream! = NULL) {
Stream.Foreach (T- & GT; {
if (order.compare (T, (T) Mass [0]) & gt; 0) Mass [0] = T;
if (order.compare (T, (T) Mass [1]) & lt; 0) Mass [1] = T;
});
}
Optional & lt;? EXTENDS T & GT; MIN = (optional & lt ;? extends t & gt;) optional.of (Mass [0]);
Optional & lt;? EXTENDS T & GT; max = (optional & lt ;? extends t & gt;) optional.of (Mass [1]);
Standard integer.compare
with null
does not compare and so NULLPOINTEREXCEPTION
, I can not initialize with zeros immediately, because Transmitted Stream & LT parameter;? EXTENDS T & GT; Stream
Not only Integer
Maybe how to fix this problem?
Answer 1, Authority 100%
public static & lt; t & gt; Pair & lt; t, t & gt; FindminMax (
Stream & lt;? EXTENDS T & GT; Stream,
Comparator & lt;? Super T & GT; Order, pair & lt; t, t & gt; Identity) {
Return stream.Reduce (
Identity,
(pair, t) - & gt; {
T min = order.compare (pair.getkey (), t) & lt; 0? pair.getKey (): T;
T Max = order.compare (pair.getvalue (), t) & gt; 0? pair.getvalue (): T;
RETURN NEW PAIR & LT; & GT; (Min, Max);
},
(P1, P2) - & gt; {
T min = order.compare (P1.getKey (), p2.getKey ()) & lt; 0? P2.getKey (): P1.getKey ();
T max = order.compare (P1.GetValue (), P2.GetValue ()) & gt; 0? P1.GetValue (): P1.GetValue ();
RETURN NEW PAIR & LT; & GT; (Min, Max);
}
);
}
Some such a nightmare ..
Public Static Void Main (String [] Args) {
Pair & Lt; Integer, Integer & GT; Identity = new pair & lt; & gt; (integer.max_value, integer.min_value);
Stream & LT; Integer & GT; s = stream.of (1,2,3,4,5,6,7,8,9,10);
Comparator & lt; Integer & gt; COMP = (Integer O1, Integer O2) - & gt; o1.compare (O1, O2);
Pair & Lt; Integer, Integer & GT; P = example.findminMax (S, COMP, Identity);
System.Out.printLN (P); // 1..10
}
PS: Alternative implementation without Identity on advice @tagirvaleev:
public static & lt; t & gt; Pair & lt; t, t & gt; FindminMax (
Stream & lt;? EXTENDS T & GT; Stream,
Comparator & lt;? Super T & GT; Order) {
Return stream.Reduce (
NULL
(pair, t) - & gt; {
if (pair == null) return new pair & lt; & gt; (t, t);
T min = order.compare (pair.getkey (), t) & lt; 0? pair.getKey (): T;
T Max = order.compare (pair.getvalue (), t) & gt; 0? pair.getvalue (): T;
RETURN NEW PAIR & LT; & GT; (Min, Max);
},
(P1, P2) - & gt; {
if (p1 == null) Return P2;
if (p2 == null) RETURN P1;
T min = order.compare (P1.getKey (), p2.getKey ()) & lt; 0? P2.getKey (): P1.getKey ();
T max = order.compare (P1.GetValue (), P2.GetValue ()) & gt; 0? P1.GetValue (): P1.GetValue ();
Return new pair & lt; & gt; (min, max);}
);
}
Answer 2, Authority 33%
Desire to make two streams from one kills a statement from the documentation on the java.util.stream
:
A Stream Should Be Operated ON (Invoking An Intermediate or Terminal
Stream Operation) Only Once. This Rules Out, For Example, “Forked”
Streams, Where The Same Source Feeds Two Or More Pipelines, OR
MultiPle Traversals of the Same Stream.
Apparently, therefore, there is nothing similar to the Internet.
In principle, you can make a calculation via stream.peek
, but for this you need or make a sequential stream, via stream.sequential
, or think about thread safety yourself, about so :
atomicreference & lt; string & gt; max = new atomicreference & lt; string & gt; ();
Comparator & lt; String & GT; compararator = compararator.naturalorder ();
System.out.PrintLN (
Arrays.stream (New String [] {"One", "Two", "Abrakadabra", "Ten", "Cat"})
.peek (Candidate - & GT; Max.updateAndget (Current - & GT; {
if (current == null) Return Candidate;
Return Comparator.comPare (Current, Candidate) & gt; = 0? Current: Candidate;
}))
.min (Comparator) + "" + optional.Ofnullable (max.get ())
);
// Conclusion: optional [Cat] Optional [Abracadabra]
For numerical primitives in the library there is a java.util.util.intsummarystatistics
(as well as double
and long
versions) from which you can get Minimum, maximum, average and number of elements in the stream. I tried to write my own same, but for objects:
Public Class ObjectSummaryStatistics & lt; t & gt; Implements Consumer & LT; T & GT; {
INT COUNT = 0;
T min = null;
T Max = NULL;
Final Comparator & LT; T & GT; Comparator;
Public Static & Lt; T & GT; Collector & LT; T, ObjectSumMaryStatistics & LT; T & GT;, ObjectSumMaryStatistics & LT; T & GT; & GT; Collector (Final Comparator & LT; T & GT; compararator) {
Objects.Requirenonnull (Comparator, "Must Supply Comparator.");
Return Collector. & lt; T, ObjectSumMaryStatistics & lt; T & GT;, ObjectSumMaryStatistics & lt; T & GT; & gt; of (
() - & gt; New ObjectSummaryStatistics & LT; T & GT; (Comparator),
ObjectSummaryStatistics :: Accept,
ObjectSummaryStatistics :: Combine,
ObjectSummaryStatistics :: FINISH,
Characteristics.identity_finish
);
}
Public ObjectSummaryStatistics (Comparator & lt; T & GT; compararator) {
Objects.Requirenonnull (Comparator, "Must Supply Comparator.");
This.comparator = compararator;
}
@Override
Public Void Accept (T Value) {
Objects.Requirenonnull (Value, "This Collector Does Not Accept Nulls");
if (Count == 0) {
min = value;
max = value;
} else {
Updatemin (Value);
Updatemax (Value);
}
COUNT + = 1;
}
Public ObjectSummaryStatistics & lt; T & GT; Combine (ObjectSummaryStatistics & LT; T & GT; Other) {
if (other.count & gt; 0) {
if (this.count == 0) {
this.min = Other.min;
this.max = Other.max;
this.Count = Other.count;
} else {
Updatemin (Other.min);
Updatemax (Other.max);
this.Count + = Other.Count;
}
}
Return this;
}
Public ObjectSummaryStatistics & lt; T & GT; FINISH () {
Return this;
}
Private Void Updatemax (T Value) {
if (Comparator.comPare (Value, Max) & GT; 0) {
max = value;
}
}
Private Void Updatemin (T Value) {
If (Comparator.comPare (Value, Min) & LT; 0) {
min = value;
}
}
Public int Count () {
RETURN COUNT;
}
Public Optional & LT; T & GT; Max () {
// If Count & GT; 0, we must have a non-empty maximum
RETURN COUNT & GT; 0? Optional.of (MAX): optional.Empty ();
}
Public Optional & LT; T & GT; min () {
RETURN COUNT & GT; 0? Optional.of (MIN): optional.Empty ();
}
@Override
Public String Tostring () {
Return "ObjectSummaryStatistics [Count =" + Count + ", min =" + min + ", max =" + max + "]";
}
}
Usage:
system.out.println (
Arrays.stream (New String [] {"One", "Two", "Abrakadabra", "Ten", "Cat"})
.collectual (Comparator. & LT; String & GT; NaturalOrder ()))
);
// Conclusion: ObjectSumMaryStatistics [count = 5, min = cat, max = abracadabab]
System.out.PrintLN (
Arrays.Stream (New String [] {})
.collectual (Comparator. & LT; String & GT; NaturalOrder ()))
);
// Conclusion: ObjectSumMaryStatistics [count = 0, min = null, max = null]
NULL
In the stream is prohibited to remove ambiguity when receiving values (stream.min
, too, with NULL
does not work).
Answer 3
I just knew about a similar task. Yes, I want to have a stream to call the min
and max
methods, when it becomes clear that only it turns out to cause only one of two, a desire to split stream appears. But in this and the catch, as I understand it. The task is setting such that we will learn to find decisions not only in the forehead, but also to look for no obvious paths. In the end, choose minimal and makimal values from any set can be in several ways.
I solved the task like this: I sorted Stream, transformed it into an array, and took the minimum element from the beginning, and the maximum out of the end. Here is the code, maybe the non-optimal, but the testing system accepted it:
public static & lt; t & gt; Void FindminMax (
Stream & lt;? EXTENDS T & GT; Stream,
Comparator & lt;? Super T & GT; ORDER
Biconsumer & lt;? Super T ,? Super T & GT; minmaxconsumer) {
Object [] Items = stream.Sorted (Order) .toarray ();
if (Items.Length == 0) {
minmaxconsumer.accept (NULL, NULL);
} else {
T min = (t) Items [0];
T max = (T) Items [items.length - 1];
minmaxconsumer.accept (Min, Max);
}
}
Answer 4
Course teacher solution:
public static & lt; t & gt; Void FindminMax (
Stream & lt;? EXTENDS T & GT; Stream,
Comparator & lt;? Super T & GT; ORDER
Biconsumer & lt;? Super T ,? Super T & GT; minmaxconsumer) {
MinmaxFinder & lt; T & GT; minmaxfinder = new minmaxfinder & lt; & gt; (Order);
stream.foreach (minmaxfinder);
minmaxconsumer.accept (minmaxfinder.min, minmaxfinder.max);
}
Private Static Class MinmaxFinder & LT; T & GT; Implements Consumer & LT; T & GT; {
Private Final Comparator & LT;? Super T & GT; Order;
T min;
T MAX;
Private MINMAXFinder (Comparator & LT ;? Super T & GT; Order) {
this.Order = order;
}
@Override
Public Void Accept (T T) {
if (min == null || Order..Compare (T, MIN) & lt; 0) {
min = t;
}
if (max == null || Order..Compare (MAX, T) & LT; 0) {
max = t;
}
}
}