Avoiding NoSuchElementException in Java 8 streams - java

This question is a follow-up to an earlier question: Adding up BigDecimals using Streams
The question related to adding up BigDecimals using Java 8 Streams and Lambda expressions. After implementing the answers given, I ran into another problem: whenever the stream is empty, the Optional::get() method throws a NoSuchElementException.
Consider the following code:
public static void main(String[] args){
LinkedList<BigDecimal> values = new LinkedList<>();
// values.add(BigDecimal.valueOf(.1));
// values.add(BigDecimal.valueOf(1.1));
// values.add(BigDecimal.valueOf(2.1));
// values.add(BigDecimal.valueOf(.1));
// Classical Java approach
BigDecimal sum = BigDecimal.ZERO;
for(BigDecimal value : values) {
System.out.println(value);
sum = sum.add(value);
}
System.out.println("Sum = " + sum);
// Java 8 approach
values.forEach((value) -> System.out.println(value));
System.out.println("Sum = " + values.stream().reduce((x, y) -> x.add(y)).get());
}
The vanilla Java code has no problem with an empty collection, but the new Java 8 code does.
What is the most elegant way to avoid a NSEE here? Certainly we could do:
System.out.println("Sum = " + values == null || values.isEmpty() ? 0 : values.stream().reduce((x, y) -> x.add(y)).get());
But is there a Java-8-ish way to handle empty collections?

You should, in this case, not be using the version of reduce that can return an Optional<BigDecimal>.
You should be using the other version, as mentioned before, that provides an identity element in case the stream is empty, that is the whole reason the identity element is there.
So you want to have:
System.out.println("Sum = " + values.stream().reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
Instead of the old version.
In this case you do not care about whether the stream is empty or not, you just want a valid result.

While typing the example to ask the question, I found the answer:
Stream::reduce() returns an Optional which has a method: orElse(). So,
System.out.println("Sum = " + values.stream().reduce((x, y) -> x.add(y)).get());
becomes
System.out.println("Sum = " + values.stream().reduce((x, y) -> x.add(y)).orElse(BigDecimal.ZERO));
So I decided to post a Q-and-A.
Lambdas are great. +1 Java.

Related

Guava iterators for nested foreach

I want to use guava iterator or java8 foreach(may be lambda expression) nested for loop and process some statements and return a long variable. Here is my code in native java. Please excuse my code may not efficient. I read over net accessing non final variables inside new java 8 foreach is not possible.
Long x = Long.valueOf(0);
Long y = Long.valueOf(0);
for(FirstLevel first : Levels)
{
if(first.getSecondLevels() == null)
{
x= x + getSomeValue(first);
}
for (SecondLevel second : first.getSecondLevels())
{
y = y + getSomeValue(second);
}
}
return x + y;
I have tried but unable to return the values. Thanks in advance for help!
Couple things:
Before approaching "refactoring" like that one you ask, I really strongly recommend learning more "pure" Java (which I assume is the case here, #javalearner). For example you can use long literals instead of manually boxing values:
long x = 0L;
long y = 0L;
Anyway...
using Guava won't help here - this is the imperative way of doing it, and with Java 7 + Guava you'd have to write awkward anonymous classes (i.e. Functions), which without language support is painful. Which brings me to...
Java 8 and Streams. This is probably the best way to go, but first you have to fix (?) your code and define actual problem - for example this statement x= x + getSomeValue(x); evaluates x each time and does not take FirstLevel into account (same is true for y and SecondLevel), so I assume what you really meant was x =+ getSomeValue(firstLevel);.
Having all that said - please be more specific what your problem really is.
EDIT:
After your clarification, using streams your code could look like this:
final long sum = levels.stream()
.mapToLong(first -> getSomeValue(first) + first.getSecondLevels().stream().mapToLong(this::getSomeValue).sum())
.sum();
or with some helper method:
final long s = levels.stream()
.mapToLong(first -> getSomeValue(first) + getSecondLevelSum(first))
.sum();
private long getSecondLevelSum(final FirstLevel first) {
return first.getSecondLevels().stream().mapToLong(this::getSomeValue).sum();
}
First of all, there is no sense in using boxed Long values and even if you once need a boxed value, you don’t need to invoke Long.valueOf, Java already does that for you when converting a long primitive to a boxed Long object.
Further, since adding long values does not depend on the order of summands, there is no reason to maintain two variable throughout the operation, when you will add them at the end anyway:
long result=0;
for(FirstLevel first: Levels) {
result += getSomeValue(first);
for(SecondLevel second: first.getSecondLevels()) {
result += getSomeValue(second);
}
}
return result;
Note that the operator += does the same as result = result + … here, but avoids the repetition of the target operand.
Assuming that both, Levels and the result of getSecondLevels, are collections you can write the same as Stream operation as
return Levels.stream()
.mapToLong(first ->
getSomeValue(first) + first.getSecondLevels().stream()
.mapToLong(second -> getSomeValue(second)).sum())
.sum();
or, alternatively
return Levels.stream()
.flatMapToLong(first -> LongStream.concat(
LongStream.of(getSomeValue(first)),
first.getSecondLevels().stream().mapToLong(second -> getSomeValue(second))))
.sum();
If Levels is an array, you have to replace Levels.stream() with Arrays.stream(Levels) and likewise, if getSecondLevels() returns an array, you have to replace first.getSecondLevels().stream() with Arrays.stream(first.getSecondLevels())

Input/output in GLPK for Java

I find a lot of GLPK for Java examples about how to specify the model (problem/constraints) to the solver and read parameters from a data file, but very little about programmatic parameter input/output.
In my case I need to submit values (array of weights and values) to a knapsack problem programmatically and postprocess the solution as well (perform addtional numeric checks on the solution found) in order to decide whether to proceed or not.
Think of the equivalent of reading a param: line from a data file without calling glp_mpl_read_data or printing details of a solution to a file without calling glp_print_mip/sol/itp.
Can you provide example code or point me to the right resource?
This is only a partial answer. I managed to solve the output part using the
GLPK.get_ipt_obj_val
GLPK.get_mip_obj_val
GLPK.get_ipt_col_val
GLPK.get_mip_col_val
functions as in the following example
static void writeMipSolution(glp_prob lp) {
String name = GLPK.glp_get_obj_name(lp);
double val = GLPK.glp_mip_obj_val(lp);
System.out.println(name + " = " + val);
int n = GLPK.glp_get_num_cols(lp);
for (int i = 1; i <= n; i++) {
name = GLPK.glp_get_col_name(lp, i);
val = GLPK.glp_mip_col_val(lp, i);
System.out.println(name + " = " + val);
}
}
Still investigating the input part, though.

Recursive Sum of digits of number(until digit is less than 10) java 8 lambdas only

I am just practicing lamdas java 8. My problem is as follows
Sum all the digits in an integer until its less than 10(means single digit left) and checks if its 1
Sample Input 1
100
Sample Output 1
1 // true because its one
Sample Input 2
55
Sample Output 2
1 ie 5+5 = 10 then 1+0 = 1 so true
I wrote a code
System.out.println(Arrays.asList( String.valueOf(number).split("") ).stream()
.map(Integer::valueOf)
.mapToInt(i->i)
.sum() == 1);
It works for the input 1 ie 100 but not for input 2 ie 55 which I clearly understand that in second case 10 is the output because the iteration is not recursive .
So how can I make this lambdas expression recursive so that it can work in second case also? I can create a method with that lambda expression and call it each time until return value is< 10 but I was thinking if there is any approach within lambdas.
Thanks
If you want a pure lambda solution, you should forget about making it recursive, as there is absolutely no reason to implement an iterative process as a recursion:
Stream.iterate(String.valueOf(number),
n -> String.valueOf(n.codePoints().map(Character::getNumericValue).sum()))
.filter(s -> s.length()==1)
.findFirst().ifPresent(System.out::println);
Demo
Making lambdas recursive in Java is not easy because of the "variable may be uninitialized" error, but it can be done. Here is a link to an answer describing one way of doing it.
When applied to your task, this can be done as follows:
// This comes from the answer linked above
class Recursive<I> {
public I func;
}
public static void main (String[] args) throws java.lang.Exception {
Recursive<Function<Integer,Integer>> sumDigits = new Recursive<>();
sumDigits.func = (Integer number) -> {
int s = Arrays.asList( String.valueOf(number).split("") )
.stream()
.map(Integer::valueOf)
.mapToInt(i->i)
.sum();
return s < 10 ? s : sumDigits.func.apply(s);
};
System.out.println(sumDigits.func.apply(100) == 1);
System.out.println(sumDigits.func.apply(101) == 1);
System.out.println(sumDigits.func.apply(55) == 1);
System.out.println(sumDigits.func.apply(56) == 1);
}
I took your code, wrapped it in { ... }s, and added a recursive invocation on the return line.
Demo.

cant sort the following tree map

for (a = 0; a < filename; a++) {
Map<Double,String> m = new HashMap<Double,String>();
String pre = "abc";
String post = ".txt";
for (int ii = 0; ii < 11; ii++) {
m.put(similarityScore[a],pre + a + post + '\n');
}
SortedSet<Double> set = new TreeSet<Double>(m.keySet());
for (Double d : set) {
System.out.println(d + " " + m.get(d));
}
}
Output :
0.5773502691896258 abc0.txt
0.5773502691896258 abc1.txt
0.5773502691896258 abc2.txt
NaN abc3.txt
0.5773502691896258 abc4.txt
NaN abc5.txt
NaN abc6.txt
NaN abc7.txt
NaN abc8.txt
0.5773502691896258 abc9.txt
NaN abc10.txt
This code should be able to sort the double values. But it displays the output on top. What happen ?
The problem is almost certainly NaN.
This is, as the name suggests, not a realy number, and behaves very strangely in terms of comparisons. Is NaN greater than, equal to, or less than 0.5773502691896258? It could be any of those results, and isn't even required to be consistent within a single execution of the program. NaN is not even equal to itself, which says something about how preconceptions of the laws of equality, and strong ordering, go out of the window when NaN is involved.
So the fix is not to use a non-numeric and expect Double.compareTo() to do what you want with it. Depending on what NaN means when returned from similarityScore(), there are several approaches you could take. If it means that it's not a match at all, you could have that method return a Double (rather than a double), return null in these cases, and then only add non-null results to the map. If these results should be displayed anyway, then perhaps you could use a result of 0.0 or -1.0, assuming that's less than any "real" similarity score. If you want something more finessed, then returning something as pure and straightforward as a primitive double is likely going to be the problem, and you may need to return your own (simple) domain class instead.
As an aside - why on earth do you create and populate a HashMap, then use a TreeSet to get the iteration order over the keys? If you simply create m as a TreeMap<Double, String> you get exactly the iteration order you want, so can just iterate overm.entrySet()`. It's clearer, more idiomatic (thus more understandable), and more efficient, so there's no reason not to do this.
for (int ii = 0; ii < 11; ii++) {
m.put(similarityScore[a],pre + a + post + '\n');
}
This puts the same value into the map 11 times - you're not referencing ii inside the loop.
for (Double d : set) {
System.out.println(d + " " + m.get(d));
}
This prints the single entry in the map.
You do the above for values 0..filename - Adding a value to the map several times, then printing it and restarting with a new map.
Map<Double,String> m = new HashMap<Double,String>();
for (a = 0; a < filename; a++) {
String pre = "abc";
String post = ".txt";
m.put(similarityScore[a],pre + a + post + '\n');
}
SortedSet<Double> set = new TreeSet<Double>(m.keySet());
for (Double d : set) {
System.out.println(d + " " + m.get(d));
}
This creates a map, populates it with values for 0..filename, then prints it sorted. You'll still have issues with NaN which isn't really sortable.
Map<Double,String> m = new TreeMap<Double,String>();
for (a = 0; a < filename; a++) {
String pre = "abc";
String post = ".txt";
m.put(similarityScore[a],pre + a + post + '\n');
}
for (Double d : m.keySet()) {
System.out.println(d + " " + m.get(d));
}
And this uses a TreeMap - No need for the intermediate Set
For any Collection to sort, the type of the value on which you are sorting should be same. And should implement comparable interface.
In your case you have NaN and Double values to sort.
Your loop means you're sorting for each filename separately. You'll need to pull the sorting out of the loop to get those values sorted. (Ooops, #Eric beat me to it.)

How to multiply 10 to an "Integer" object in Java?

How do I multiply 10 to an Integer object and get back the Integer object?
I am looking for the neatest way of doing this.
I would probably do it this way:
Get int from Integer object, multiply it with the other int and create another Integer object with this int value.
Code will be something like ...
integerObj = new Integer(integerObj.intValue() * 10);
But, I saw a code where the author is doing it this way: Get the String from the Integer object, concatenate "0" at the end and then get Integer object back by using Integer.parseInt
The code is something like this:
String s = integerObj + "0";
integerObj = Integer.parseInt(s);
Is there any merit in doing it either way?
And what would be the most efficient/neatest way in general and in this case?
With Java 5's autoboxing, you can simply do:
Integer a = new Integer(2); // or even just Integer a = 2;
a *= 10;
System.out.println(a);
The string approach is amusing, but almost certainly a bad way to do it.
Getting the int value of an Integer, and creating a new one will be very fast, where as parseInt would be fairly expensive to call.
Overall, I'd agree with your original approach (which, as others have pointed out, can be done without so much clutter if you have autoboxing as introduced in Java 5).
The problem with the second way is the way Strings are handled in Java:
"0" is converted into a constant String object at compile time.
Each time this code is called, s is constructed as a new String object, and javac converts that code to String s = new StringBuilder().append(integerObj.toString()).append("0").toString() (StringBuffer for older versions). Even if you use the same integerObj, i.e.,
String s1 = integerObj + "0";
String s2 = integerObj + "0";
(s1 == s2) would be false, while s1.equals(s2) would be true.
Integer.parseInt internally calls new Integer() anyway, because Integer is immutable.
BTW, autoboxing/unboxing is internally the same as the first method.
Keep away from the second approach, best bet would be the autoboxing if you're using java 1.5, anything earlier your first example would be best.
The solution using the String method is not so good for a variety of reasons. Some are aesthetic reasons others are practical.
On a practical front more objects get created by the String version than the more normal form (as you have expressed in your first example).
On an aesthetic note, I think that the second version obscures the intent of the code and that is nearly as important as getting it to produce the result you want.
toolkit's answer above is correct and the best way, but it doesn't give a full explanation of what is happening.
Assuming Java 5 or later:
Integer a = new Integer(2); // or even just Integer a = 2;
a *= 10;
System.out.println(a); // will output 20
What you need to know is that this is the exact same as doing:
Integer a = new Integer(2); // or even just Integer a = 2;
a = a.intValue() * 10;
System.out.println(a.intValue()); // will output 20
By performing the operation (in this case *=) on the object 'a', you are not changing the int value inside the 'a' object, but actually assigning a new object to 'a'.
This is because 'a' gets auto-unboxed in order to perform the multiplication, and then the result of the multiplication gets auto-boxed and assigned to 'a'.
Integer is an immutable object. (All wrapper classes are immutable.)
Take for example this piece of code:
static void test() {
Integer i = new Integer(10);
System.out.println("StartingMemory: " + System.identityHashCode(i));
changeInteger(i);
System.out.println("Step1: " + i);
changeInteger(++i);
System.out.println("Step2: " + i.intValue());
System.out.println("MiddleMemory: " + System.identityHashCode(i));
}
static void changeInteger(Integer i) {
System.out.println("ChangeStartMemory: " + System.identityHashCode(i));
System.out.println("ChangeStartValue: " + i);
i++;
System.out.println("ChangeEnd: " + i);
System.out.println("ChangeEndMemory: " + System.identityHashCode(i));
}
The output will be:
StartingMemory: 1373539035
ChangeStartMemory: 1373539035
ChangeStartValue: 10
ChangeEnd: 11
ChangeEndMemory: 190331520
Step1: 10
ChangeStartMemory: 190331520
ChangeStartValue: 11
ChangeEnd: 12
ChangeEndMemory: 1298706257
Step2: 11
MiddleMemory: 190331520
You can see the memory address for 'i' is changing (your memory addresses will be different).
Now lets do a little test with reflection, add this onto the end of the test() method:
System.out.println("MiddleMemory: " + System.identityHashCode(i));
try {
final Field f = i.getClass().getDeclaredField("value");
f.setAccessible(true);
f.setInt(i, 15);
System.out.println("Step3: " + i.intValue());
System.out.println("EndingMemory: " + System.identityHashCode(i));
} catch (final Exception e) {
e.printStackTrace();
}
The additional output will be:
MiddleMemory: 190331520
Step2: 15
MiddleMemory: 190331520
You can see that the memory address for 'i' did not change, even though we changed its value using reflection.
(DO NOT USE REFLECTION THIS WAY IN REAL LIFE!!)

Categories

Resources