Alternative to stream.reduce for foreach loop in Java - java

I have the following for each loop:
int someOtherVal = 0;
List<Applicators> applicatorList = List.of(applicator1, applicator2);
MyClass result = initialClassValue;
for(Applicator applicator: applicatorList) {
result = applicator.apply(result, someOtherVal);
}
The closest I can get to it using Stream API is:
applicatorList.stream()
.reduce(
initialClassValue,
(intermediateResult, applicator) -> applicator.apply(intermediateResult, someOtherVal),
(intermediateResult1, intermediateResult2) -> intermediateResult1 // complete garbage but need to provide for parallel streams which I am not using
)
Is there some other way to implement this which does not involve the needless overriding of combiner function?
My beef with using combiner function is that -
I am not using parallel streams, so combining of intermediate results should not be required
the garbage combiner override actually doesn't make sense in this context

You can do it by not specifying the initial value in the reduce method. However, this too has its disadvantages. Here is a related example:
create my own sum lambda (could have used Integer::sum)
it returns an Optional<T> of some type T.
due to the lack of an initial value it returns the first via orElse. But then, that is what your method would do if only one value. Or you could just return the optional and check if a value was present.
BinaryOperator<Integer> sumThem = (a,b)->a + b;
int[] arr = {1,2,3,4,5,6,7};
int sum = Arrays.stream(arr).boxed().reduce(sumThem::apply).orElse(1);
But there is nothing wrong with using a loop and may be the best way to go.

Related

How iterate over a List and check it against the Enum values with a Stream

I have a list and I want to find out if it contains any other elements than what I have in the enum.
I have this working:
boolean containsMyEnumCode(List<String> processCodes) {
if (null != processCodes) {
for (final String process : processCodes) {
if (!(Arrays.stream(MyEnumCode.values()).anyMatch((p) -> p.name().equals(process)))) {
return true;
}
}
}
return false;
}
This works, but how could I replace for loops with a stream, and have it in fewer lines?
Instead of null check, you can use Stream.ofNullable() (available from Java 9 onwards) which will create a stream with a single element (list of processors) or empty stream. Apply flatMap() to turn it to a stream of strings. And then apply anyMatch() as a terminal operation which will determine whether at least one process in the stream matches with the given predicate.
Note: that condition !Arrays.stream().anyMatch() means that none of elements in the stream should match the predicate passed to the anyMatch(). And that is the meaning of the operation noneMath(). A change of the terminal operation will make the condition more readable by eliminating the need in logical not in front of it Arrays.stream().noneMath().
Another improvement that is made to this code was inspired by suggestions from Holger and k314159.
Stream of enum constants Arrays.stream(MyEnumCode.values())... from the original code that is used in the condition discussed above has a performance overhead. Method values() creates an array of enum constants at every call. And it will be invoked for every element in the list. Therefore it makes sense to introduce a local variable that will store a Set of enum-names and check every element in the stream against this set.
Also as Holger pointed out null-friendly solution will disguise the problem. anyMatch() will return false in case of an empty stream and this result will be accepted as valid instead of raising NPE, and then this list can be stored somewhere and will cause problems in the future.
Since I'm providing two solutions here I've implemented one in such a way that it will raise an exception with a custom message, and another as being null-friendly by using Stream.ofNullable().
public static boolean containsNonEnumCode(List<String> processCodes) {
Set<String> names = getEnumNames(MyEnumCode.class);
return Stream.ofNullable(processCodes)
.flatMap(List::stream)
.anyMatch(process -> !names.contains(process));
}
Solution for Java 8 (requested by PO in the comment) implemented as null-hostile by using Objects.requireNonNull().
public static boolean containsNonEnumCode(List<String> processCodes) {
Set<String> names = getEnumNames(MyEnumCode.class);
return Objects.requireNonNull(processCodes, "processCodes list in null")
.stream()
.anyMatch(process -> !names.contains(process));
}
The method below expects the Class of an enum as a parameter and generates a Set of enum names.
public static <T extends Enum<T>> Set<String> getEnumNames(Class<T> enumClass) {
return EnumSet.allOf(enumClass).stream()
.map(T::name)
.collect(Collectors.toSet());
}
Starting with Optional.ofNullable on the collection passed through as a parameter you could do something like this:
Optional.ofNullable(processCodes).stream()
.flatMap(Collection::stream)
.anyMatch(code -> Arrays.stream(MyEnumCode.values()).anyMatch(v -> v.name().equals(code)));

Default andThen() method in BiFunction interface

There's a default method andThen() in the BiFunction interface (java.util.function package).
default <V> BiFunction<T,U,V> andThen(Function<? super R,? extends V> after)
The documentation says:
Returns a composed function that first applies this function to its input, and then applies the after function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the composed function.
It's little confusing to understand what the explanation means. As per my understanding, a composed function is returned when the default andThen() method is invoked. This composed function is invoked on the types T and U that returns the type V. Finally, there's and after function that is invoked on the types R and V.
What's the need of this method? How does it actually fit in the picture?
It's little confusing to understand what the explanation means.
To explain it as simple as I can, the method andThen returns a function that first applies a given function to an input and then applies another function to the result of that application.
Assume we had two functions f and g , function f doing some logic and function g doing some other type of logic so when you compose f.andThen(g) that essentially means g(f(x)) i.e. we first apply the function given as argument f(x) and then apply the function g to the result.
Example:
BiFunction<Integer, Integer, Integer> f = Math::addExact;
Function<Integer, Integer> g = e -> e * 2;
System.out.println(f.andThen(g).apply(10,10)); // 40
We first call function f(10, 10) and then take the result of that which is 20, pass it to the function g(20) and that is executed multiplying 20 by 2 hence yielding 40.
To be honest the syntax to call a function in Java is not the best it can be so I can understand when someone looks at this the first time it might be difficult to grasp and gets harder to follow the more you compose functions, for example in C# one could simply do g(f(10, 10)) which visibly to the eye is easier to follow, read and understand.
What's the need of this method? How does it actually fit in the
picture?
In my experience, it's not common that I've composed functions as shown above but a typical scenario I could imagine is if you have various utility methods that do some logic where the result of one function is further passed to other functions for processing in which case you can then use function composition to create various transformation pipelines by composing the utility methods.
I think the main purpose of the andThen function is to make your code more readable and more functional.
Let's look at and example:
BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y;
Function<Integer, Integer> negate = x -> -x;
BiFunction<Integer, Integer, Integer> newFunction = add.andThen(negate);
Guess what newFunction does? It adds andThen negates two numbers! See how similar to English this line is:
BiFunction<Integer, Integer, Integer> newFunction = add.andThen(negate);
If you call .apply(1, 2), you know you'd get -3.
Sure, you could do this without using andThen:
BiFunction<Integer, Integer, Integer> newFunction = (x, y) -> negate.apply(add.apply(x, y))
But look how unreadable that is!
Coding functionally can sometimes make things much easier to read and understand.
Consider f1.andThen(f2) :
First, f1 will take 2 elements and result in only 1
after that, f2 will take the result of f1 and tranform it to another result
BiFunction<Integer, Integer, Integer> plus10 = (i1, i2) -> i1 + i2 + 10;
Function<Integer, Integer> mult = i -> i * 5;
System.out.println(plus10.andThen(mult).apply(5, 6)); // (5+6+10) *5 = 105
It's a way to reduce computation
int val1 = plus10.apply(5, 6);
int res1 = mult.apply(val1);
int res2 = plus10.andThen(mult).apply(5, 6);
System.out.println(res1 == res2); //true
It's more and more usefull when you have several function to use, because there is the same method for Function, so you can chain them :
System.out.println(plus10.andThen(mult).andThen(mult).andThen(mult).apply(5, 6));
// (5+6+10)*5*5*5 = 2625
It's easier understood with an example:
BiFunction<Integer, Integer, String> f =
(n1, n2) -> String.format("result is %s", n1+n2);
And the "composed function" is:
BiFunction<Integer, Integer, String> f1 =
f.andThen(string -> string.toUpperCase());
Note that the second function still takes the same argument types as the first one, although it internally only needs a String to execute its logic.
Consider the invocation:
System.out.println(f1.apply(2, 3));
Which outputs RESULT IS 5, that is: it calls first function and then calls the second function with the result of the first. So it's simply understood as f1(f(x, y)) with the ultimate input being the input required by f, and the ultimate result being the result yielded by f1.

Java double colon operator from compile time to byte code generation?

In this question the author uses the following example:
#Override
public final OptionalInt max() {
return reduce(Math::max); //this is the gotcha line
}
So in this case it looks as if max() is a proxy for Math.max on the instance of this class. However there are no arguments passed to max, so does java 8 compile this to something like (Pseudo code):
#Override
public final OptionalInt max(Integer a, Integer b) {
//If neither a or b are null
return new OptionalInt.of(Math.max(a,b));
//Otherwise return empty because we can't compare the numbers
return OptionalInt.empty()
}
Also how would one write the javadoc for something like this?
So in this case it looks as if max() is a proxy for Math.max on the instance of this class. However there are no arguments passed to max, so does java 8 compile this to something like (Pseudo code):
#Override
public final OptionalInt max(Integer a, Integer b) {
//If neither a or b are null
return new OptionalInt.of(Math.max(a,b));
//Otherwise return empty because we can't compare the numbers
return OptionalInt.empty()
}
Not quite :). Let's start by figuring out what the reduce operator actually does. The documentation explains that it performs a reduction on a sequence of numbers by applying an algorithm that is logically equivalent to the following:
public OptionalInt reduce(IntBinaryOperator op) {
boolean foundAny = false;
int result = 0;
for (int element : [this stream]) {
if (!foundAny) {
foundAny = true;
result = element;
}
else {
result = op.applyAsInt(result, element);
}
}
return foundAny ? OptionalInt.of(result)
: OptionalInt.empty();
}
Seems simple enough. If you can tell it how to take two numbers and 'reduce' or 'combine' them into one, then reduce knows how to extend that logic to reduce an entire sequence into a single number. It handles the edge cases and the aggregation for you. All it needs from you is a function that takes in two numbers and gives it one back. That function should conform to the functional interface IntBinaryOperator.
A functional interface is an interface that is meant to describe a single function. Specifically, it describes the argument types and the return type. The rest is largely superfluous. The signature for an IntBinaryOperator looks like this:
int applyAsInt(int left, int right);
You can provide a function that conforms to this specification in several ways. Prior to Java 8, you might have done something like this:
stream.reduce(
new IntBinaryOperator() {
public int applyAsInt(int a, int b) {
return b > a ? b : a;
}
}
);
Java 8 gives us a shorthand form for functional interfaces called lambda expressions. These are a bit more concise, and while they are conceptually similar to anonymous inner classes, they're not quite the same thing.
stream.reduce((a, b) -> b > a ? b : a);
Both functions above are equivalent: they take in two numbers and return the larger of the two. As it turns out, every standard programming library has a function that does exactly the same thing. In Java, that function is Math.max. So rather than writing this logic myself, I can delegate to Math.max:
stream.reduce((a, b) -> Math.max(a, b));
But wait! All reduce wants is a function that takes two numbers and returns one. Math.max does that, so do I even need to wrap it in a lambda? It turns out I don't; I can tell reduce to just call Math.max directly:
stream.reduce(Math::max);
This says "I know you want a function, so I'm show you by name where to find one that's already been written". The compiler knows that Math.max conforms to the (int, int) -> int specification we need, so it emits some bytecode telling the VM how to 'bootstrap' it once it's needed. When the JVM hits your call to reduce, it calls a special method that generates a wrapper class implementing IntBinaryOperator that delegates to Math.max in its implementation of applyAsInt. It only performs this 'bootstrapping' step once. Since calling Math.max doesn't rely on anything other than the two numbers that get passed in, it can cache that implementation and use it the next time you wind up on this code path.
Pre Java 8, this would have been written as:
public MyMathInteface {
OptionalInt max(Integer a, Integer b);
}
public static final MyMathInterface reducing = new MyMathInterface() {
#Override
public OptionalInt max(Integer a, Integer b) {
return OptionalInt.of(Math.max(a, b));
}
};
#Override
public final OptionalInt max() {
return reduce(reducing);
}
Then reduce would be defined as:
public static OptionalInt reduce(MyMathInteface toReduce) {
return toReduce.max(someValueA, someValueB);
}
So to answer your question, no arguments are passed to Math::max, because those values are retrieved by the reduce function. They could be constants or they could be retrieved from some other place.
In any case, the use of the max method in this way is called a method reference, that is where you do SomeObject::method. That :: operator creates a method reference. It returns a function, but does not call the function. The user (reduce) is responsible for calling the function.

why java.util.Set can't return any value?

java.util.Set specifies only methods that return all records (via Iterator or array).
Why is there no option to return any value from Set?
It has a lot of sense in the real life. For example, I have a bowl of strawberries and I want to take just one of them. I totally don't care which one.
Why I can't do the same in java?
This is not answerable. You'd have to ask the original designers of the Java collections framework.
One plausible reason is that methods with non-deterministic behavior tend to be problematic:
They make unit testing harder.
They make bugs harder to track down.
They are more easily misunderstood and misused by programmers who haven't bothered to read the API documentation.
For hashtable-based set organizations, the behavior a "get some element" method is going to be non-deterministic, or at least difficult to determine / predict.
By the way, you can trivially get some element of a non-empty set as follows:
Object someObject = someSet.iterator().next();
Getting a truly (pseudo-)random element is a bit more tricky / expensive because you can't index the elements of a set. (You need to extract all of the set elements into an array ...)
On revisiting this, I realized that there is another reason. It is simply that Set is based on the mathematical notion of a set, and the elements of a set in mathematics have no order. It is simply meaningless to talk about the first element of a mathematical set.
A java.util.Set is an unordered collection; you can see it as a bag that contains things, but not in any particular order. It would not make sense to have a get(int index) method, because elements in a set don't have an index.
The designers of the standard Java library didn't include a method to get a random element from a Set. If you want to know why, that's something you can only speculate about. Maybe they didn't think it was necessary, or maybe they didn't even think about it.
It's easy to write a method yourself that gets a random element out of a Set.
If you don't care about the index of the elements, try using Queue instead of Set.
Queue q = new ArrayDeque();
q.element(); // retrieves the first object but doesn't remove
q.poll(); // retrieves and removes first object
While a plain Set is in no particular, SortedSet and NavigableSet provide a guaranteed order and methods which support this. You can use first() and last()
SortedSet<E> set = ...
E e1 = set.first(); // a value
E e2 = set.last(); // also a value.
Actually the iterator is a lot better then using get(position) (which is something you can do on a java.util.List). It allows for collection modifications during the iterations for one thing. The reason you don't have them in sets is probably because most of them don't guarantee order of insertion. You can always do something like new ArrayList<?>(mySet).get(position)
If you are not concerned with performance you can create a new type and back the data in an arraylist.
( Please note before donwvoting this is just an naive implementation of the idea and not the proposed final solution )
import ...
public class PickableSet<E> extends AbstractSet<E>{
private final List<E> arrayList = new ArrayList<E>();
private final Set<E> hashSet = new HashSet<E>();
private final Random random = new Random();
public boolean add( E e ) {
return hashSet.add( e ) && arrayList.add( e );
}
public int size() {
return arrayList.size();
}
public Iterator<E> iterator() {
return hashSet.iterator();
}
public E pickOne() {
return arrayList.get( random.nextInt( arrayList.size() ) );
}
}
Of course, since you're using a different interface you'll have to cast to invoke the method:
Set<String> set = new PickableSet<String>();
set.add("one");
set.add("other");
String oneOfThem = ((PickableSet)set).pickOne();
ie
https://gist.github.com/1986763
Well, you can with a little bit of work like this
Set<String> s = new HashSet<String>();
Random r = new Random();
String res = s.toArray(new String[0])[r.nextInt(s.toArray().length)];
This grabs a randomly selected object from the set.

How to keep a "things done" count in a recursive algorithm in Java?

I have a recursive algorithm which steps through a string, character by character, and parses it to create a tree-like structure. I want to be able to keep track of the character index the parser is currently at (for error messages as much as anything else) but am not keen on implementing something like a tuple to handle multiple returned types.
I tried using an Integer type, declared outside the method and passed into the recursive method, but because it's final, recursive call increments are "forgotten" when I return. (Because the increment of the Integer value makes the passed-by-value object reference point at a new object)
Is there a way to get something similar to work which won't pollute my code?
Since you've already discovered the pseudo-mutable integer "hack," how about this option:
Does it make sense for you to make a separate Parser class? If you do this, you can store the current state in a member variable. You probably need to think about how you're going to handle any thread safety issues, and it might be overkill for this particular application, but it might work for you.
It's kind of a hack, but sometimes I use an AtomicInteger, which is mutable, to do things like this. I've also seen cases where an int[] of size 1 is passed in.
The current solution I am using is:
int[] counter = {0};
and then pass it to the recursive algorithm:
public List<Thing> doIt (String aString, int[] counter) { ... }
and when I want to increment it:
counter[0]++;
Not super elegant, but it works...
Integers are immutable, which means that when you pass it as an argument it creates a copy rather than a reference to the same item. (explanation).
To get the behavior you're looking for, you can write your own class which is like Integer only mutable. Then, just pass it to the recursive function, it is incremented within the recursion, and when you access it again after the recursion is over it will still maintain its new values.
Edit: Note that using an int[] array is a variation on this method... In Java, arrays are also passed by reference rather than copied like primitives or immutable classes.
You could just use a static int class variable that gets incremented each time your doIt method is called.
You could also do:
private int recurse (int i) {
if (someConditionkeepOnGoing) {
i = recurse(i+1);
}
return i;
}
To be honest I would recode the function to make it a linear algorithm that uses a loop. This way you have no chance of running out of heap space if you are stepping through an extremely large string. Also, you would not need to have a the extra parameter just to keep track of the count.
This also would probably have the result of making the algorithm faster because it does not need to make a function call for every character.
Unless of course there is a specific reason it needs to be recursive.
One possibility I can think of is to store the count in a member variable of the class. This of course assumes that the public doIt method is only called by a single thread.
Another option is to refactor the public method to call a private helper method. The private method takes the list as a parameter and returns the count. For example:
public List<Thing> doIt(String aString) {
List<Thing> list = new ArrayList<Thing>();
int count = doItHelper(aString, list, 0);
// ...
return list;
}
private int doItHelper(String aString, List<Thing> list, int count) {
// ...
// do something that updates count
count = doItHelper(aString, list, count);
// ...
return count;
}
This assumes that you can do the error handling in the public doIt method, since the count variable isn't actually passed back to the caller. If you need to do that, you could of course throw an exception:
public List<Thing> doIt(String aString) throws SomeCustomException {
List<Thing> list = new ArrayList<Thing>();
int count = doItHelper(aString, list, 0);
// ...
if (someErrorOccurred) {
throw new SomeCustomException("Error occurred at chracter index " + count, count);
}
return list;
}
It's difficult to know whether that will help without knowing more about how your algorithm actually works.

Categories

Resources