Java 8 stream map reusing assigned variable - java

I'm aware that title may be a little confusing but I couldn't come up with a better one so let me explain what I mean...
I have this piece of code:
int spacing = Integer.MAX_VALUE;
for (Edge edge : edges) {
if (!union.connected(edge.getStart(), edge.getEnd())) {
spacing = Math.min(spacing, edge.getWeight());
}
}
Is there a way to turn this code into java 8 code?
Of course, first step is filtering which is simple, but then it becomes tricker because I would have to reuse computed variable spacing in Stream::map method and I have no idea is that possible.

I'm not entirely sure about the syntax (I can't test it), but it should work with something like this :
int spacing = edges.stream()
.filter(edge -> !union.connected(edge.getStart(), edge.getEnd()))
.min (Collectors.comparing(Edge::getWeight))
.map (Edge::getWeight) // get the weight of the min Edge
.orElse(Integer.MAX_VALUE);
Not sure about the Comparator passed to min.
In case the code above doesn't work, you can mapToInt first (assuming getWeight() returns int) :
int spacing = edges.stream()
.filter(edge -> !union.connected(edge.getStart(), edge.getEnd()))
.mapToInt(Edge::getWeight)
.min ()
.orElse(Integer.MAX_VALUE);

Related

How to code these conditional statements in more elegant & scalable manner

In my software, I need to decide the version of a feature based on 2 parameters. Eg.
Render version 1 -> if (param1 && param2) == true;
Render version 2 -> if (!param1 && !param2) == true;
Render version 3 -> if only param1 == true;
Render version 4 -> if only param2 == true;
So, to meet this requirement, I wrote a code which looks like this -
if(param1 && param2) //both are true {
version = 1;
}
else if(!param1 && !param2) //both are false {
version = 2;
}
else if(!param2) //Means param1 is true {
version = 3;
}
else { //Means param2 is true
version = 4;
}
There are definitely multiple ways to code this but I finalised this approach after trying out different approaches because this is the most readable code I could come up with.
But this piece of code is definitely not scalable because -
Let say tomorrow we want to introduce new param called param3. Then
the no. of checks will increase because of multiple possible
combinations.
For this software, I am pretty much sure that we
will have to accommodate new parameters in future.
Can there be any scalable & readable way to code these requirements?
EDIT:
For a scalable solution define the versions for each parameter combination through a Map:
Map<List<Boolean>, Integer> paramsToVersion = Map.of(
List.of(true, true), 1,
List.of(false, false), 2,
List.of(true, false), 3,
List.of(false, true), 4);
Now finding the right version is a simple map lookup:
version = paramsToVersion.get(List.of(param1, param2));
The way I initialized the map works since Java 9. In older Java versions it’s a little more wordy, but probably still worth doing. Even in Java 9 you need to use Map.ofEntries if you have 4 or more parameters (for 16 combinations), which is a little more wordy too.
Original answer:
My taste would be for nested if/else statements and only testing each parameter once:
if (param1) {
if (param2) {
version = 1;
} else {
version = 3;
}
} else {
if (param2) {
version = 4;
} else {
version = 2;
}
}
But it scales poorly to many parameters.
If you have to enumerate all the possible combinations of Booleans, it's often simplest to convert them into a number:
// param1: F T F T
// param2; F F T T
static final int[] VERSIONS = new int[]{2, 3, 4, 1};
...
version = VERSIONS[(param1 ? 1:0) + (param2 ? 2:0)];
I doubt that there is a way that would be more compact, readable and scalable at the same time.
You express the conditions as minimized expressions, which are compact and may have meaning (in particular, the irrelevant variables don't clutter them). But there is no systematism that you could exploit.
A quite systematic alternative could be truth tables, i.e. the explicit expansion of all combinations and the associated truth value (or version number), which can be very efficient in terms of running-time. But these have a size exponential in the number of variables and are not especially readable.
I am afraid there is no free lunch. Your current solution is excellent.
If you are after efficiency (i.e. avoiding the need to evaluate all expressions sequentially), then you can think of the truth table approach, but in the following way:
declare an array of version numbers, with 2^n entries;
use the code just like you wrote to initialize all table entries; to achieve that, enumerate all integers in [0, 2^n) and use their binary representation;
now for a query, form an integer index from the n input booleans and lookup the array.
Using the answer by Olevv, the table would be [2, 4, 3, 1]. A lookup would be like (false, true) => T[01b] = 4.
What matters is that the original set of expressions is still there in the code, for human reading. You can use it in an initialization function that will fill the array at run-time, and you can also use it to hard-code the table (and leave the code in comments; even better, leave the code that generates the hard-coded table).
Your combinations of parameters is nothing more than a binary number (like 01100) where the 0 indicates a false and the 1 a true.
So your version can be easily calculated by using all the combinations of ones and zeroes. Possible combinations with 2 input parameters are:
11 -> both are true
10 -> first is true, second is false
01 -> first is false, second is true
00 -> both are false
So with this knowledge I've come up with a quite scalable solution using a "bit mask" (nothing more than a number) and "bit operations":
public static int getVersion(boolean... params) {
int length = params.length;
int mask = (1 << length) - 1;
for(int i = 0; i < length; i++) {
if(!params[i]) {
mask &= ~(1 << length - i - 1);
}
}
return mask + 1;
}
The most interesting line is probably this:
mask &= ~(1 << length - i - 1);
It does many things at once, I split it up. The part length - i - 1 calculates the position of the "bit" inside the bit mask from the right (0 based, like in arrays).
The next part: 1 << (length - i - 1) shifts the number 1 the amount of positions to the left. So lets say we have a position of 3, then the result of the operation 1 << 2 (2 is the third position) would be a binary number of the value 100.
The ~ sign is a binary inverse, so all the bits are inverted, all 0 are turned to 1 and all 1 are turned to 0. With the previous example the inverse of 100 would be 011.
The last part: mask &= n is the same as mask = mask & n where n is the previously computed value 011. This is nothing more than a binary AND, so all the same bits which are in mask and in n are kept, where as all others are discarded.
All in all, does this single line nothing more than remove the "bit" at a given position of the mask if the input parameter is false.
If the version numbers are not sequential from 1 to 4 then a version lookup table, like this one may help you.
The whole code would need just a single adjustment in the last line:
return VERSIONS[mask];
Where your VERSIONS array consists of all the versions in order, but reversed. (index 0 of VERSIONS is where both parameters are false)
I would have just gone with:
if (param1) {
if (param2) {
} else {
}
} else {
if (param2) {
} else {
}
}
Kind of repetitive, but each condition is evaluated only once, and you can easily find the code that executes for any particular combination. Adding a 3rd parameter will, of course, double the code. But if there are any invalid combinations, you can leave those out which shortens the code. Or, if you want to throw an exception for them, it becomes fairly easy to see which combination you have missed. When the IF's become too long, you can bring the actual code out in methods:
if (param1) {
if (param2) {
method_12();
} else {
method_1();
}
} else {
if (param2) {
method_2();
} else {
method_none();
}
}
Thus your whole switching logic takes up a function of itself and the actual code for any combination is in another method. When you need to work with the code for a particular combination, you just look up the appropriate method. The big IF maze is then rarely looked at, and when it is, it contains only the IFs themselves and nothing else potentially distracting.

Getting the inverse of a function that uses summation in Java

I have a program with one class, which looks like this.
public class Functions {
public static void main(String[] args) {
System.out.println(summationFunction(1)); //Prints 13
System.out.println(summationFunction(2)); //Prints 29
System.out.println(summationFunction(3)); //Prints 48
System.out.println(summationFunction(4)); //Prints 70
}
public static int summationFunction(int input) {
int summedNumber = 0;
int i = input;
while (i > 0) {
summedNumber += i * 3;
i--;
}
return 10 * input + (summedNumber);
}
}
So, this program will take in a given number and apply this function to it:
And this all works well (I have run the class Functions and everything prints just as it's supposed to.) BUT, I need to find the inverse of this function, and I need to be able to translate it to code; I do not know how to do this.
I basically need a function that will return values like this:
public static void main(String[] args) {
System.out.println(summationFunction(13)); //Prints 1
System.out.println(summationFunction(29)); //Prints 2
System.out.println(summationFunction(48)); //Prints 3
System.out.println(summationFunction(70)); //Prints 4
}
which, (as you can tell) is the opposite of the original function.
So to sum everything up, I need a function that will return the inverse of my original function (summationFunction), and I would like to know how I would model this or if there is a quick solution, in code.
One more thing: I know that I can have the method take an input and search for the most similar output of the original method, but I would like to see if there is a simpler way to do this which does not involve searching, thus giving a quicker output speed. And if you wish you can safely assume that the input of the inversed function will always be a number which will give an integer output, like 13, 29, 48, 70, etc...
By the way, if you are going to downvote the question, will you at least give a reason somewhere? The comments perhaps? I can not see any reason that this question is eligible for being downvoted, and a reason would help.
Wolfram Alpha to the rescue !
It tells you that this function can be written as :
1/24*(6*x+23)^2-529/24
So if you want to solve f(x)=a, you have :
x = 1/6*(sqrt(24*a+529)-23)
a = 70
# => x = 4
Note : Using Wolfram shouldn't prevent you from finding the answer on your own.
sum(something*i) is equal to something*sum(i) because something (3 in this case ) doesn't depend on i.
sum(i,i=1..n) is equal to n*(n+1)/2, and it's easy to prove (see Wikipedia)
So your function becomes 10*x+3*x*(x+1)/2
Expanded, it is :
(3 x^2)/2+(23 x)/2
You need to solve (3 x^2)/2+(23 x)/2 = 70, in other words :
(3 x^2)/2+(23 x)/2 - 70 = 0
It is a quadratic equation, with a=3/2, b=23/2 and c=-70 or c=-29 or c=....
You sum can be written like this 3*x*(x+1)/2 so you have equation 10*x + 3*x*(x+1)/2 = y you need to solve it.
Wolfram alpha tells that result will be 1/6.0 * (-23.0+sqrt(529.0+24.0 * y))

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())

What is better/faster in Java: 2 method calls or 1 object call

I'm afraid this is a terribly stupid question. However, I can't find an answer to it and therefore require some help :)
Let's start with a simplification of my real problem:
Assume I have a couple of boxes each filled with a mix of different gems.
I'm now creating an object gem which has the attribute colour and a method getColour to get the colour of the gem.
Further I'm creating an object box which has a list of gems as attribute and a method getGem to get a gem from that list.
What I want to do now is to count all gems in all boxes by colour. Now I could either do something like
int sapphire = 0;
int ruby = 0;
int emerald = 0;
for(each box = i)
for(each gem = j)
if(i.getGem(j).getColour().equals(“blue”)) sapphire++;
else if(i.getGem(j).getColour().equals(“red”)) ruby++;
else if(i.getGem(j).getColour().equals(“green”)) emerald++;
or I could do
int sapphire = 0;
int ruby = 0;
int emerald = 0;
String colour;
for(each box = i)
for(each gem = j)
colour = i.getGem(j).getColour();
if(colour.equals(“blue”)) sapphire++;
else if(colour.equals(“red”)) ruby++;
else if(colour.equals(“green”)) emerald++;
My question is now if both is essentially the same or should one be preferred over the other? I understand that a lot of unnecessary new string objects are produced in the second case, but do I get a speed advantage in return as colour is more “directly” available?
I would dare to make a third improvement:
int sapphire = 0;
int ruby = 0;
int emerald = 0;
for(each box = i) {
for(each gem = j) {
String colour = i.getGem(j).getColour();
if(“blue”.equals(colour)) sapphire++;
else if(“red”.equals(colour)) ruby++;
else if(“green”.equals(colour)) emerald++;
}
}
I use a local variable inside the for-loop. Why? Because you probably need it only there.
It is generally better to put STATIC_STRING.equals(POSSIBLE_NULL_VALUE).
This has the advantage: easier to read and should have no performance problem. If you have a performance problem, then you should consider looking somewhere else in your code. Related to this: this answer.
conceptually both codes have equal complexity i.e.: O(i*j). But if calling a method and get a returned value are considered to be two processes then the complexity of your first code will be 4*O(i*j).(consider O(i*j) as a function) and of your second code will be O(i*(j+2)). although this complexity difference is not considerable enough but if you are comparing then yes your first code is more complex and not a good programming style.
The cost of your string comparisons is going to wipe out all other considerations in this sort of approach.
You would be better off using something else (for example an enum). That would also expand automatically.
(Although your for each loop isn't proper Java syntax anyway so that's a bit odd).
enum GemColour {
blue,
red,
green
}
Then in your count function:
Map<GemColour, Integer> counts = new EnumMap<GemColour, Integer>(GemColour.class);
for (Box b: box) {
for (Gem g: box.getGems() {
Integer count = counts.get(g.getColour());
if (count == null) {
count=1;
} else {
count+=1;
}
counts.put(g.getColour(), count);
}
}
Now it will automatically extend to any new colors you add without you needing to make any code changes. It will also be much faster as it does a single integer comparison rather than a string comparison and uses that to put the correct value into the correct place in the map (which behind the scenes is just an array).
To get the counts just do, for example:
counts.get(GemColour.blue);
As has been pointed out in the comments the java Stream API would allow you to do all of this in one line:
boxes.stream().map(Box::getGems).flatMap(Collection::stream).collect(groupingBy‌​‌​(Gem::getColour, counting()))
It's less easy to understand what it is doing that way though.

Java Recursion - Did I do this right? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
My job is to write a recursive version to this method. From what I understand Recursion is starting with a base call (if something then return) followed by an else which unwinds back to the original base. Like starting with a deck, adding on to the deck then removing cards from the deck until you are back to the original deck.
With that in mind here it is.
public static long fact(int n)
{
long result = 1;
while(n > 0)
{
result = result * n;
n = n - 1;
}
return result;
}
//my recursive version:
public static void recFact(int n)
{
if(n==0)
{
return n; // ir 0 it really doesn't matter right?
}
else
{
return recFact(n-1);
}
}
This is just an example test problem for an exam I have coming up, just want to make sure I have a handle on recursion. Did I do this right? If not what am I missing? please no answers in questions, just tell me what I did wrong and maybe some advice on better ways to understand it.
Thanks.
No, this recursive solution is not correct.
For every positive n, you're just return rectFact(n-1), which will recourse until you reach 0, at which point it will return. In other words, your function will always return 0. You're missing the part where you multiply the current n with rectFact(n-1). Additionally, note that 0! is 1, not 0:
public static int recFact(int n)
{
if(n==0)
{
return 1;
}
else
{
return n * recFact(n-1);
}
}
And finally, since the if clause returns, the else is somewhat redundant. This doesn't affect the method's correctness, of course, but IMHO the code looks cleaner without it:
public static int recFact(int n)
{
if(n==0)
{
return 1;
}
return n * recFact(n-1);
}
Your recursive version does no multiplication, and it will return zero for any input. So no, you didn't do it right.
But, the recursive version DOES recurse, so you have that going for you! To understand what's going wrong, walk through a very simple case.
Client calls recFact(3)
This will return to client recFact(2)
Which will return to above recFact(1)
Which will return to above recFact(0)
Which will return to above 0.
There are two major things going wrong:
Your base case is wrong (zero is too low)
You're not doing any multiplication
Good attitude about not wanting the solution handed to you! Hopefully these pointers wil help you figure it out.
EDIT: Apparently I misunderstood your grammar and you did want the solution.
Any recursive function needs three things:
The terminating condition: This tells the function when to stop calling itself. This is very important to avoid infinite recursion and avoid stack overflow exceptions.
The actual processing: You need to run the actual processing within each function. In your non recursive case, this was result = result * n. This is missing from your recursive version!
A collector/agggregator variable: You need some way to store the partial result of the recursive calls below you. So you need some way to return the result of recFact so that you can include it in processing higher up in the call chain. Note that you say return recFact(n - 1) but in the definition recFact returns void. That should probably be an int.
Based from your example you are missing the return type of your recFact which is int
Also recFact will always return 0 because you are not multiplying n each time to the recursion call of the method.
There are two ways to write recursive routines. One is the "standard" way that we all are taught. This is one entry point that must first check to see if the recursive chain is at an end (the escape clause). If so, it returns the "end of chain" value and ends the recursion. If not at the end, it performs whatever calculation it needs to get a partial value according to the level and then calls itself passing a value the next increment closer to the end of the chain.
private final int InitialValue = 15;
System.out.println( "Fact(" + InitialValue + ") = " + recFact( InitialValue ) );
public int recFact( int val ){
if( val < 2 ){
return 1;
}
else{
return recFact( val - 1 ) * val; // recursive call
}
}
//Output: "Fact(15) = 2004310016"
In regular recursion, a partial answer is maintained at each level which is used to supplement the answer from the next level. In the code above, the partial answer is val. When first called, this value is 15. It takes this value and multiplies it by the answer from Fact(14) to supply the complete answer to Fact(15). Fact(14) got its answer by multiplying 14 by the answer it got from Fact(13) and so on.
There is another type of recursion called tail recursion. This differs in that partial answers are passed to the next level instead of maintained at each level. This sounds complicated but in actuality, make the recursion process much simpler. Another difference is that there are two routines, one is non recursive and sets up the recursive routine. This is to maintain the standard API to users who only want to see (and should only have to see)
answer = routine( parameter );
The non-recursive routines provides this. It is also a convenient place to put one-time code such as error checking. Notice in the standard routine above, if the user passed in -15 instead of 15, the routine could bomb out. That means that in production code, such a test must be made. But this test will be performed every time the routine is entered which means the test will be made needlessly for all but the very first time. Also, as this must return an integer value, it cannot handle an initial value greater than 19 as that will result in a value that will overflow the 32-bit integer container.
public static final int MaxFactorialSeq = 20;
private final int InitialValue = 15;
System.out.println( "Fact(" + InitialValue + ") = " + recFact( InitialValue ) );
public int recFact( int value ){
if( value < 0 || value > MaxFactorialSeq ){
throw new IllegalArgumentException(
"Factorial sequence value " + value + " is out of range." );
}
return recFact( value, 1 ); // initial invocation
}
private int recFact( int val, int acc ){
if( val < 2 ){
return acc;
}
else{
return recFact( val - 1, acc * val ); // recursive call
}
}
//Output: "Fact(15) = 2004310016"
Notice the public entry point contains range checking code. This is executed only once and the recursive routine does not have to make this check. It then calls the recursive version with an initial "seed" of 1.
The recursive routine, as before, checks to see if it is at the end of the chain. If so, it returns, not 1 as before, but the accumulator which at this point has the complete answer. The call chain then just rewinds back to the initial entry point in the non-recursive routine. There are no further calculations to be made as the answer is calculated on the way down rather than on the way up.
If you walk though it, the answer with standard recursion was reached by the sequence 15*14*13*...*2*1. With tail recursion, the answer was reached by the sequence 1*15*14*...*3*2. The final answer is, of course, the same. However, in my test with an initial value of 15, the standard recursion method took an average of 0.044 msecs and the tail recursion method took an average of 0.030 msecs. However, almost all that time difference is accounted for by the fact that I have the bounds checking in my standard recursion routine. Without it, the timing is much closer (0.036 to 0.030) but, of course, then you don't have error checking.
Not all recursive routines can use tail recursion. But then, not all recursive routines should be. It is a truism that any recursive function can be written using a loop. And generally should be. But a Factorial function like the ones above can never exceed 19 levels so they can be added to the lucky few.
The problem with recursion is that to understand recursion you must first understand recursion.
A recursive function is a function which calls itself, or calls a function which ultimately calls the first function again.
You have the recursion part right, since your function calls itself, and you have an "escape" clause so you don't get infinite recursion (a reason for the function not to call itself).
What you are lacking from your example though is the actual operation you are performing.
Also, instead of passing a counter, you need to pass your counter and the value you are multiplying, and then you need to return said multiplied value.
public static long recFact(int n, long val)
{
if(n==1)
{
return val;
}
else
{
return recFact(n-1, val) * n;
}
}

Categories

Resources