Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
So in an attempt to keep up with the times, I would like to learn what I can about Java 8's new functional operations. Beyond the opinions of which looks nicer, which is totally opinion based, would someone like to describe in detail the positives(and possibly negatives) in using Java 8's new functional programming style to iterate arrays?
This is what I mean:
Pre-Java 8:
for(Object item: itemList){
item.doSomething();
}
Java 8:
itemList.stream().forEach((item) -> {
item.doSomething();
});
The answers have enlightened me, so I will write something to demonstrate it's potential.
static int pos = 0;
public static void main(String[] args) {
List<Worker> workers = Arrays.asList(new Worker[1000]);
workers.replaceAll(worker -> new Worker(pos++));
workers.parallelStream().forEach(Worker::startJob);
}
public static class Worker {
final int pos;
public Worker(int pos) {
this.pos = pos;
}
public synchronized void startJob() {
try {
wait(100);
} catch (InterruptedException ex) {
Logger.global.log(Level.SEVERE, null, ex);
}
System.out.println("Finished... " + pos);
}
}
Only a partial answer, but the general point of the iterators is moving from external iteration to internal iteration. The foreach just a replacement, but consider something like the following (from Java 8 Lambdas) simulating the throwing of two dice:
public Map < Integer, Double > parallelDiceRolls() {
double fraction = 1.0 / N;
return IntStream.range( 0, N) .parallel()
.mapToObj( twoDiceThrows())
.collect( groupingBy( side -> side, summingDouble( n -> fraction)));
}
This is running a parallel operation against the stream, removing all external iteration requirements and all manual threading requirements. It replaces 50-60 lines of code.
It also moves from a focus on how to accomplish something (such as the OP's pre-Java 8 example) to what to accomplish.
Consider a Artist class that has an .isFrom(String) method. In the OP's first example, to count how many are from Liverpool, the code would be something like:
int count = 0;
for (Artist artist : allArtists) {
if (artist.isFrom("Liverpool")) {
count++;
}
}
Notice that the the desire to accumulate is lost in the loop and the filtering. Contrast with:
allArtists.stream()
.filter(artist -> artist.isFrom("Liverpool")
.count();
Now the logic is clear -- a filtering and a count. The iteration is now internal rather than external.
There are many additional examples, rationales, and preferences. But I think it is more than "beauty" -- it is a focus on the what, not the how when one considers iteratation.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 12 months ago.
Improve this question
I'm working on creating some Java methods to make writing code quicker and more efficient, and right now I'm trying to make a simple loop I'm calling "repeat."
It will work something like this:
repeat(number of times to repeat) {
code to be repeated
}
So for example:
repeat(3) {
System.out.println("hi")
}
Would display:
hi
hi
hi
How can I make a method/function like this? I also need it to work as a nested loop.
repeat(3) {
System.out.println("hi")
}
Java does not support this grammar. If you want to support this via the grammar, try another language that supports closures
Another way you can try, Java can implement it by lambda
public static void main(String[] args) {
repeat(3, () -> {
System.out.println("hi");
});
}
public static void repeat(int count, Runnable function) {
for(int i = 0; i < count; i++) {
function.run();
}
}
If you really wanted to avoid all for loops you could use a recursive version of #math-chen's solution:
public static void repeat(int count, Runnable function) {
if (count > 0) {
function.run();
repeat(count - 1, function);
}
}
As the recursive call is at the end of the method, this "tail-call" can in theory be optimised to not use any extra stack, but the JVM may not do that. (And experiment shows that it doesn't)
This question already has answers here:
How to compute average of multiple numbers in sequence using Java 8 lambda
(7 answers)
Closed 6 years ago.
In the following class:
I want to get average of foo and bar in List<HelloWorld> helloWorldList
#Data
public class HelloWorld {
private Long foo;
private Long bar;
}
OPTION 1: JAVA
Long fooSum, barSum;
for(HelloWorld hw: helloWorldList){
fooSum += hw.getFoo();
barSum += hw.getBar();
}
Long fooAvg = fooSum/helloWorldList.size();
Long barAvg = barSum/helloWorldList.size();
OPTION 2 : JAVA 8
Double fooAvg = helloWorldList.stream().mapToLong(HelloWorld::foo).average().orElse(null);
Double barAvg = helloWorldList.stream().mapToLong(HelloWorld::bar).average().orElse(null);
Which approach is better ?
Is there any better way to get these values ?
Answer edit: This question has been marked duplicate but after reading comments from bradimus i ended up implementing this:
import java.util.function.Consumer;
public class HelloWorldSummaryStatistics implements Consumer<HelloWorld> {
#Getter
private int fooTotal = 0;
#Getter
private int barTotal = 0;
#Getter
private int count = 0;
public HelloWorldSummaryStatistics() {
}
#Override
public void accept(HelloWorld helloWorld) {
fooTotal += helloWorld.getFoo();
barTotal += helloWorld.getBar();
count++;
}
public void combine(HelloWorldSummaryStatistics other) {
fooTotal += other.fooTotal;
barTotal += other.barTotal;
count += other.count;
}
public final double getFooAverage() {
return getCount() > 0 ? (double) getFooTotal() / getCount() : 0.0d;
}
public final double getBarAverage() {
return getCount() > 0 ? (double) getBarTotal() / getCount() : 0.0d;
}
#Override
public String toString() {
return String.format(
"%s{count=%d, fooAverage=%f, barAverage=%f}",
this.getClass().getSimpleName(),
getCount(),
getFooAverage(),
getBarAverage());
}
}
Main Class:
HelloWorld a = new HelloWorld(5L, 1L);
HelloWorld b = new HelloWorld(5L, 2L);
HelloWorld c = new HelloWorld(5L, 4L);
List<HelloWorld> hwList = Arrays.asList(a, b, c);
HelloWorldSummaryStatistics helloWorldSummaryStatistics = hwList.stream()
.collect(HelloWorldSummaryStatistics::new, HelloWorldSummaryStatistics::accept, HelloWorldSummaryStatistics::combine);
System.out.println(helloWorldSummaryStatistics);
Note: As suggested by others if you need high precision BigInteger etc can be used.
The answers/comments you got so far don't mention one advantage of a streams-based solution: just by changing stream() to parallelStream() you could turn the whole thing into a multi-threaded solution.
Try doing that with "option 1"; and see how much work it would need.
But of course, that would mean even more "overhead" in terms of "things going on behind the covers costing CPU cycles"; but if you are talking about large datasets it might actually benefit you.
At least you could very easily see how turning on parallelStreams() would influence execution time!
If you want to find average value in list of integers it is better to use classic approach with iterating.
Streams have some overhead and JVM has to load classes for stream usage. But also JVM has JIT with lots of optimizations.
Please beware of incorrect banchmarking. Use JMH
Streams are good and effective when your iteration operation is not such a simple thing as two integers sum.
Also streams allow you to parallelize code. There is no direct criteria when parallelize is better than single thread. As for me - if function call takes over 100ms - you can parrallelize it.
So, if your dataset processing takes >100ms try parallelStream
If not - use iterating.
P.S. Doug Lea - "When to use parallel streams"
Which approach is better ?
When you say "better", do you mean "closer to the sample's true average" or "more efficient" or what? If efficiency is your goal, streams entail a fair amount of overhead that is often ignored. However, they provide readability and conciser code. It depends upon what you're trying to maximize, how large your datasets are, etc.
Perhaps rephrase the question?
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
I have a HashMap of "buttons" which can be clicked with the key being the location (x and y coordinates) of the button. Every time new data is received from the database the buttons rearrange themselves and update their positions in the map and other values associated with the "button" object. Currently I have buttons as an immutable object so new buttons need to be created each time I receive new data.
When I thought of a real life example of this (buying a new, different colour version of your house instead of painting the one you already have) it seemed a bit wasteful to keep creating objects instead of just reusing the old ones, is this the best way to do it?
Creating new objects usually means allocating new memory, an operation that is quite expensive and something which should be avoided if a function really needs to be optimized.
It's hard (if not impossible) to say if it will be faster to create new objects or not in your specific case without any code. If we're talking about a list of 10 buttons it wont matter, but if we're talking about a list of trillions on buttons, you should probably try to reassign their values instead.
Below is a small example that illustrates the difference between creating new objects and reassigning a single value of an instance, if I understood you question correctly it should be somewhat similar to your case. The output on my machine can be seen below.
package org.stackoverflow;
import java.util.ArrayList;
public class Example {
public static class MyObject {
private double value;
public MyObject(double value) {
this.setValue(value);
}
public final void setValue(double value) {
this.value = value;
}
public double getValue() {
return this.value;
}
}
public static void main(String[] args) {
long start = 0;
ArrayList<MyObject> objects = new ArrayList<MyObject>();
start = System.currentTimeMillis();
for (int i = 0; i < 1000000; ++i) {
objects.add(new MyObject(Math.random()));
}
System.out.println("Time to create 1.000.000 objects: "
+ Long.toString(System.currentTimeMillis() - start)
+ " ms.");
start = System.currentTimeMillis();
for (int i = 0; i < 1000000; ++i) {
objects.get(i).setValue(Math.random());
}
System.out.println("Time to reassign 1.000.000 objects: "
+ Long.toString(System.currentTimeMillis() - start)
+ " ms.");
}
}
Output
Time to create 1.000.000 objects: 323 ms.
Time to reassign 1.000.000 objects: 31 ms.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I was browsing through questions regarding continue keyword to get a better understanding of it and I stumbled upon this line in this answer
These can be maintenance timebombs because there is no immediate link between the "continue"/"break" and the loop it is continuing/breaking other than context;
I have this for loop:
for(Object obj : myArrayList){
if(myArrayList.contains(someParticularData)){
continue;
}
//do something
}
Now, my question is - Is it okay to use continue in the manner that I have done above or does it have any issues? If yes, what is the alternative approach that I can follow? Any kind of guidance would help. Thank you.
Update: My objective in this particular situation would be to iterate over a Collection ( ArrayList, in this case), and check if that contains some particular data and skip that iteration if it is true.
I was pointed out that myArrayList.contains(someParticularData) is a one time operation and that it would be better off to perform that check outside the loop, which is what I was looking for. Also, I learnt that if I can use continue based on some condition if(someConditon), I can very well avoid it by using if(!someCondition).
for(Object obj : myArrayList){
if(someCondition){
continue;
}
//do something
}
can be replaced with:
for(Object obj : myArrayList){
if(!someCondition){
//do something
}
}
IMHO, as far as you don't have a lot (like 2-3 continue/break/return), maintenance will be fine.
This code is of little use
for(Object obj : myArrayList) {
// You're checking again and agian the condition that's loop independent
if(myArrayList.contains(someParticularData)){
continue;
}
//do something
}
A more effective implementation is (check whether you need the loop at all first)
if (!myArrayList.contains(someParticularData))
for(Object obj: myArrayList) {
//do something
}
continue is convenient in conditions like that:
for(Object obj : myArrayList) {
// Check for each item: do we need to proceed this item
if (someArrayList.contains(obj))
continue;
//do something
}
Whenever you are looping on some value range, you are processing on each of the value comes between the initial and final one...
For example if you are making addition of odd numbers.
it is convenient to use loop which will be incremented by 2 rather than continuing for each odd value,
for (int i = 0; i < 100 ; i=i+2){
// do addition
}
but if you are modifying your value that is being checked within the loop, than continue or break is good practice to implement.
for example,
boolean flag = false;
// flag will be modified in some iteration of loop, but you don't know which.
for ( int i = 0 ; i < 100 ; i++ ) {
if ( flag ) {
continue;
}
// flag modified somewhere..
}
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 9 years ago.
Improve this question
I have written the following code, which first validates a matrix and then it would invoke a private function to add them, it validation is a success. Now its a good practice to validate once again in a private function according to effective java. However, if validation step itself is long, do we need to validate everything in the private function ? If not then where to draw the line ?
private static void check(int[][] m1, int[][] m2, char op) {
if (m1 == null || m2 == null) {
throw new NullPointerException("No input matrix should be null.");
}
/**
* Switch case was thought to be beneficial in case of future extensibility.
* http://en.wikipedia.org/wiki/Switch_statement#Advantages_and_disadvantages
*/
switch (op) {
case 'a' : if (m1.length != m2.length && m1[0].length != m2[0].length) throw new IllegalArgumentException("bla bla"); else break;
case 'm' : if (m1[0].length != m2.length) throw new IllegalArgumentException("bla bla"); else break;
}
}
public static int[][] add (int[][] m1, int[][] m2) {
check (m1, m2, 'a');
return add(m1, m2, m1.length - 1, m1[0].length - 1);
}
private static int[][] add (int[][] m1, int[][] m2, int rows, int cols) {
assert m1 != null;
assert m2 != null;
// final can be returned check Arrays docjar line 2843.
final int[][] m = new int[rows + 1][cols + 1];
for (int i = 0; i <= rows ; i++) {
for (int j = 0; j <= cols; j++ ) {
m[i][j] = m1[i][j] + m2[i][j];
}
}
return m;
}
Here I have only validated if matrices are null.. but that is useless if I dont validate the other parameters passed. Once again this question is generic so please dont suggest code improvement. This code only serves as an example to a much broader question - how much to validate while calling a private function. Thanks,
Validation is one of reasons to split the application / library to layers.
The "public" layer should validate. Usually that's a service layer or API, or, in general, the classes/methods which other developers will call.
Then, in the low-level operations, validation is ommited and the method does expect the input to be already validated. This fact should be mentioned in javadoc.
Related note - I adopted a technique when I first collect the validation violations to a List and then report all of them in one exception. This is very convenient for the user so he doesn't have to go through an annoying cycle fix/try/fix/try/fix/try, but rather fix,fix,fix,fix,try.
In my humble opinion, explicitly checking for null references and the like (eg different sized matrices) in low level operations constitutes "code bloat". In this example: Validation should be done after each operation which loads or otherwise modifies the STRUCTURE of the matrix... all subsequent operations upon the VALUES in the matrix should presume valid matrices.
I'd also do my "operation specific" validations directly in each operation-method, unless/until the validation code becomes "bulky", in which case I'd factor it out into a separate "validate*Operation*" method.
This is JUST my opinion... based on experience of reporting "bad input" to the user at the appropriate time, and helps me to seek destroy my own mistakes during testing and debugging.
Cheers. Keith.
PS: Another alternative is Assertions, which are only active when a "debug flag" is turned on, and not in production where efficiency may be an issue.