Rewrite cycle with break to lambda - java

I had a cycle for counter:
List<Mt4Report> history = ...
int counter = 0;
for (Mt4Report item : history) {
if (item.getProfit().compareTo(BigDecimal.ZERO) < 0) {
counter++;
} else {
break;
}
}
How I can write the same idea with lambda expression something .findFirst().ifPresent but withholding break statement?

With Java-9 and above, you can use takeWhile approach as :
int counter = (int) history.stream()
.takeWhile(item -> item.getProfit().compareTo(BigDecimal.ZERO) < 0)
.count();
For the Java-8 solution, you can look into a custom implementation of takeWhile provided in this answer. On the other hand, a less efficient implementation with the use of indexOf could be to perform:
int count = history.stream()
.filter(ite -> ite.getProfit().compareTo(BigDecimal.ZERO) >= 0)
.findFirst()
.map(history::indexOf)
.orElse(history.size());
As Holger suggested to improve the above solution, you can make use of the IntStream with findFirst:
int count = IntStream.range(0, history.size())
.filter(ix -> history.get(ix).getProfit() .compareTo(BigDecimal.ZERO) >= 0)
.findFirst()
.orElse(history.size());

As per Java 8 there is no direct solution for this problem, which is basically stopping a Stream using a Predicate.
In Java 9 you have the takeWhile() method but in Java 8, there is no such thing like that.
Please refer to this post

Related

The code showing Time Limit Exceed erroe, could some one explain, where is problem in this code [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last year.
Improve this question
LeetCode 485
Given a binary array nums, return the maximum number of consecutive 1's in the array.
Example 1:
Input: nums = [1,1,0,1,1,1]
Output: 3
Explanation: The first two digits or the last three digits are consecutive 1s. The maximum number of consecutive 1s is 3.
---------Solution:-------
public int findMaxConsecutiveOnes(int[] nums) {
int maxConsSize = Integer.MIN_VALUE;
int i = -1, j=-1, k=0;
while(k<nums.length){
while(k<nums.length && nums[k] == 1){
k++;
i++;
}
if(nums[k] == 0){
maxConsSize = Math.max(maxConsSize,i-j);
j = i;
}
}
maxConsSize = Math.max(maxConsSize,i-j);
return maxConsSize;
}
Warning: This is not direct answer (for this "do my homework" question)
You should use (or learn to use) debugger in your IDE (trust me, IDE, e.g. Eclipse will help you a lot in your beginnings).
The easiest (I'm not saying smartest) way, how to know what the program is doing (when you need to know, like in this case) is to add some print statements, e.g. add System.out.println("k=" + k) into your program (in a while loop).
You might want to watch this youtube video.
You have an infinity loop. Try run this:
public class Test {
public static void main(String[] args) {
int maxConsSize = Integer.MIN_VALUE;
int[] nums = {1,1,0,1,1,1};
int i = -1, j=-1, k=0;
System.out.println(nums.length);
while(k<nums.length){
while(k<nums.length && nums[k] == 1){
k++;
i++;
System.out.println("k = " + k);
}
if(nums[k] == 0){
maxConsSize = Math.max(maxConsSize,i-j);
j = i;
}
}
maxConsSize = Math.max(maxConsSize,i-j);
System.out.println(maxConsSize);
}
}
Output:
6
k = 1
k = 2
After reading the first 0 you are in infinite loop. You have made this task very complicated :)
It's probably not the best solution, but it should be faster
public int findMaxConsecutiveOnes(int[] nums) {
int maxCons = 0;
int currentCons = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 0) {
if (currentCons > maxCons) {
maxCons = currentCons;
}
currentCons = 0;
} else {
currentCons++;
}
}
if (currentCons > maxCons) {
maxCons = currentCons;
}
return maxCons;
}
}
There are two basic forms of loops:
for-each, for-i or sometimes called ranged for
Use that for a countable number of iterations.
For example having an array or collection to loop through.
while and do-while (like until-loops in other programming languages)
Use that for something that has a dynamic exit-condition. Bears the risk for infinite-loops!
Your issue: infinite loop
You used the second form of a while for a typical use-case of the first. When iterating over an array, you would be better to use any kind of for loop.
The second bears always the risk of infinite-loops, without having a proper exit-condition, or when the exit-condition is not fulfilled (logical bug). The first is risk-free in that regard.
Recommendation to solve
Would recommend to start with a for-i here:
// called for-i because the first iterator-variable is usually i
for(int i=0; i < nums.length, i++) {
// do something with num[i]
System.out.println(num[i]):
}
because:
it is safer, no risk of infinite-loop
the iterations can be recognized from the first line (better readability)
no counting, etc. inside the loop-body
Even simpler and idiomatic pattern is actually to use a for each:
for(int n : nums) {
// do something with n
System.out.println(n):
}
because:
it is safer, no risk of infinite-loop
the iterations can be recognized from the first line (better readability)
no index required, suitable for arrays or lists
no counting at all
See also:
Java For Loop, For-Each Loop, While, Do-While Loop (ULTIMATE GUIDE), an in-depth tutorial covering all about loops in Java, including concepts, terminology, examples, risks

Does Java 8 provide a good way to repeat a function based on specific condition?

I am having the old style while loop like below:
int i = 1, n = 5;
while(i <= n) {
if (doSomething()) {
break;
}
i++;
}
Is it possible to do it in a good way in Java 8?
You can do it using IntStream and findFirst short-circuiting terminal operation. And when ever doSomething() method returns true the execution of stream pipeline will be terminated
IntStream.range(1,5)
.filter(i -> doSomething())
.findFirst();
Even though you have mentioned Java 8, if you are going to use Java 9 or above and need to know the number of times the loop was executed, then do as follows:
long count = IntStream.range(1,6)
.takeWhile(i -> !doSomething()) // loop continued till doSomething is true
.count();
takeWhile was introduced in Java 9.
Plain old approach:
while(i <= n && !doSomething()) {
// do something here
i++;
}
Pretty clear and concise.
This is tidier:
for (int i = 0; i < 5 && !doSomething(); i++);

Java 8: Replace traditional for loop [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 4 years ago.
Improve this question
What's the best & concise way to change the code given below in Java 8:
static int[] breakingRecords(int[] scores) {
int lowest = 0, highest = 0, countlow = 0, counthigh = 0;
for (int i = 0; i < scores.length; i++) {
if (i == 0) {
lowest = scores[0];
highest = scores[0];
} else {
if (scores[i] < lowest) {
lowest = scores[i];
countlow++;
} else if (scores[i] > highest) {
highest = scores[i];
counthigh++;
}
}
}
int rc[] = {counthigh, countlow};
return rc;
}
Note: I know that I can use:
IntStream.range(0, 10).forEach(
i -> {
if (i == 0) {
...
}
But to do so, I need to declare all the variables as AtomicInteger which makes the code verbose & hard to read.
There must be a better way than using AtomicIntegers. Is there?
Let's be much more simpler. You are getting the maximum and minimum values in a Stream.
IntStream provides method for that :
OptionalInt max()
OptionalInt min()
Here is a quick way of how to use it :
int[] array = {5, 6, 10, 2, 5};
OptionalInt max = Arrays.stream(array).max();
OptionalInt min = Arrays.stream(array).min();
System.out.println("min : " + min.getAsInt());
System.out.println("max : " + max.getAsInt());
Note that you get OptionalInt, so you should check for empty values, but this only occurs if the IntStream itself is empty. So you can check that before you even read the array.
EDIT: this solution was proposed before the question include the return showing that the important part is the countHigh and countLow part.
Assuming that "the best way" actually refers to the most performant way ... you are probably already there (or very close to it)!
You see, using IntStream and lambdas might help with readability, but that will not magically increase performance. To the contrary. These constructs come with a certain amount of overhead!
In other words: if your ultimate goal is to write the code that solves the underlying problem in the most efficient way, then "old school" is (most likely) your best option.
Streams play nicely for readability (when used wisely), and they can help with efficient filtering and such, and of course, when using parallelStream() you might be able to get results quicker (by using more threads). But for straight forward simple computations on some array of ints, none of these advantages apply!
You could achieve that by using a custom comparator, which accepts a predicate when to increment the counter and an access method to be able to get said counter:
public class IncrementingComparator implements Comparator<Integer>{
private final IntPredicate doIncrement;
private int count;
public IncrementingComparator(IntPredicate doIncrement){
this.doIncrement = doIncrement;
}
#Override
public int compare(Integer o1, Integer o2){
final int compareResult = o1.compareTo(o2);
if(doIncrement.test(compareResult)){
count++;
}
return compareResult;
}
public int count(){
return count;
}
}
You then could create 2 instances of above class:
final IncrementingComparator maxCmp = new IncrementingComparator(i -> i > 0);
final IncrementingComparator minCmp = new IncrementingComparator(i -> i < 0);
Which then can be used inside the min() and max() operations of Stream:
final Optional<Integer> max = Arrays.stream(array)
.boxed()
.max(maxCmp);
final Optional<Integer> min = Arrays.stream(array)
.boxed()
.min(minCmp);
After the min and max are found, you could then extract the count values from each comparator:
final int maxCount = maxCmp.count();
final int minCount = minCmp.count();
Note: Because the Comparators have an internal state, they can only be used once. (Or one could add a reset() method to set the count variable back to 0.

Kotlin loop with irregular steps

I have been trying to translate a Java for expression into Kotlin which produces this sequence:
1,2,4,8,16,32,64
This is the Java code:
for(int i = 1; i < 100; i = i + i) {
System.out.printf("%d,", i);
}
The only way I have found to translate this into Kotlin is:
var i = 1
while (i < 100) {
print("$i,")
i += i
}
I have tried to use step expressions, but this does not seem to work. Is there any way to express this type of sequence more elegantly in Kotlin?
I know you can have code like this one using Kotlin + Java 9:
Stream.iterate(1, { it <= 100 }) { it!! + it }.forEach { print("$it,") }
But this relies on Java libraries and I would prefer Kotlin native libraries.
You can use the generateSequence function to create an infinite sequence, then use takeWhile to limit it at a specific value and then use forEach instead of a for-in construct to handle each iteration:
generateSequence(1) { it + it }.takeWhile { it < 100 }.forEach { print("$it,") }

Converting Java to Scala

I am trying to learn Scala, so can anyone tell me how to convert the following in scala:
for (int t = 0; true; t++)
Thank you in advance.
With imperative style you can write (as you do in Java):
var t = 0
while(true) {
t+=1
...
}
With lazy functional this could be:
def ints(n: Int = 0): Stream[Int] = Stream.cons(n, ints(n+1))
ints().map(t => ...)
Using built-in functions:
Iterator.from(0).map ( t => .... )
The common use case with such infinite structures, is to take infinite stream or iterator, perform some operations on it, and then take number of results:
Iterator.from(0).filter(t => t % 1 == 0).map(t => t*t).take(10).toList
As I mentioned in the comments, your question does not seem to make much sense - please add more detail.
For now, the closest Scala translation I can come up with would be:
Stream from 0
You can use while or for.
You can use for
for(i<-0 to 100) {
println(i)
}
or you use until when you want to increment by N number
for(i <- 5 until 55 by 5) {
println(i)
}
or you better use while
var i = 0
while(true) {
...
i+=1
}
or also do-while
var i = 0
do {
...
i += 1
} while(true)
Have a look at : http://www.simplyscala.com/
and test it out by yourself
Also, in my blog I did some posts about imperative scala where I used for and while loops you can have a look there.
http://carlosqt.blogspot.com/search/label/Scala
A simple for comprehension in scala looks mostly this way:
for (i <- 0 until 10) {
// do some stuff
}

Categories