Is there any functional difference between AtomicInteger.updateAndGet() and AtomicInteger.accumulateAndGet()? - java

Is there any scenario in which AtomicInteger.accumulateAndGet() can't be replaced with AtomicInteger.updateAndGet(), or is it just a convenience for method references?
Here's a simple example where I don't see any functional difference:
AtomicInteger i = new AtomicInteger();
i.accumulateAndGet(5, Math::max);
i.updateAndGet(x -> Math.max(x, 5));
Obviously, the same goes for getAndUpdate() and getAndAccumulate().

When in doubt, you may look into implementation:
public final int accumulateAndGet(int x,
IntBinaryOperator accumulatorFunction) {
int prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSet(prev, next));
return next;
}
public final int updateAndGet(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return next;
}
They differ only in single line and obviously accumulateAndGet could be expressed easily via updateAndGet:
public final int accumulateAndGet(int x,
IntBinaryOperator accumulatorFunction) {
return updateAndGet(prev -> accumulatorFunction.applyAsInt(prev, x));
}
So updateAndGet is somewhat more basic operation and accumulateAndGet is a useful shortcut. Such shortcut might be especially helpful if your x is not effectively final:
int nextValue = 5;
if(something) nextValue = 6;
i.accumulateAndGet(nextValue, Math::max);
// i.updateAndGet(prev -> Math.max(prev, nextValue)); -- will not work

There are cases where an instance creation can be avoided by using accumulateAndGet.
This is not really a functional difference but it might be useful to know about.
Consider the following example:
void increment(int incValue, AtomicInteger i) {
// The lambda is closed over incValue. Because of this the created
// IntUnaryOperator will have a field which contains incValue.
// Because of this a new instance must be allocated on every call
// to the increment method.
i.updateAndGet(value -> incValue + value);
// The lambda is not closed over anything. The same
// IntBinaryOperator instance can be used on every call to the
// increment method.
//
// It can be cached in a field, or maybe the optimizer is able
// to reuse it automatically.
IntBinaryOperator accumulatorFunction =
(incValueParam, value) -> incValueParam + value;
i.accumulateAndGet(incValue, accumulatorFunction);
}
Instance creations are generally not expensive but can be important to get rid of in short operations that are used very frequently in performance sensitive locations.
More information about when lambda instances are reused can be found in this answer.

Related

local variable is not known within for loop in lambda java 8 [duplicate]

Modifying a local variable in forEach gives a compile error:
Normal
int ordinal = 0;
for (Example s : list) {
s.setOrdinal(ordinal);
ordinal++;
}
With Lambda
int ordinal = 0;
list.forEach(s -> {
s.setOrdinal(ordinal);
ordinal++;
});
Any idea how to resolve this?
Use a wrapper
Any kind of wrapper is good.
With Java 10+, use this construct as it's very easy to setup:
var wrapper = new Object(){ int ordinal = 0; };
list.forEach(s -> {
s.setOrdinal(wrapper.ordinal++);
});
With Java 8+, use either an AtomicInteger:
AtomicInteger ordinal = new AtomicInteger(0);
list.forEach(s -> {
s.setOrdinal(ordinal.getAndIncrement());
});
... or an array:
int[] ordinal = { 0 };
list.forEach(s -> {
s.setOrdinal(ordinal[0]++);
});
Note: be very careful if you use a parallel stream. You might not end up with the expected result. Other solutions like Stuart's might be more adapted for those cases.
For types other than int
Of course, this is still valid for types other than int.
For instance, with Java 10+:
var wrapper = new Object(){ String value = ""; };
list.forEach(s->{
wrapper.value += "blah";
});
Or if you're stuck with Java 8 or 9, use the same kind of construct as we did above, but with an AtomicReference...
AtomicReference<String> value = new AtomicReference<>("");
list.forEach(s -> {
value.set(value.get() + s);
});
... or an array:
String[] value = { "" };
list.forEach(s-> {
value[0] += s;
});
This is fairly close to an XY problem. That is, the question being asked is essentially how to mutate a captured local variable from a lambda. But the actual task at hand is how to number the elements of a list.
In my experience, upward of 80% of the time there is a question of how to mutate a captured local from within a lambda, there's a better way to proceed. Usually this involves reduction, but in this case the technique of running a stream over the list indexes applies well:
IntStream.range(0, list.size())
.forEach(i -> list.get(i).setOrdinal(i));
If you only need to pass the value from the outside into the lambda, and not get it out, you can do it with a regular anonymous class instead of a lambda:
list.forEach(new Consumer<Example>() {
int ordinal = 0;
public void accept(Example s) {
s.setOrdinal(ordinal);
ordinal++;
}
});
As the used variables from outside the lamda have to be (implicitly) final, you have to use something like AtomicInteger or write your own data structure.
See
https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#accessing-local-variables.
An alternative to AtomicInteger is to use an array (or any other object able to store a value):
final int ordinal[] = new int[] { 0 };
list.forEach ( s -> s.setOrdinal ( ordinal[ 0 ]++ ) );
But see the Stuart's answer: there might be a better way to deal with your case.
Yes, you can modify local variables from inside lambdas (in the way shown by the other answers), but you should not do it. Lambdas have been made for functional style of programming and this means: No side effects. What you want to do is considered bad style. It is also dangerous in case of parallel streams.
You should either find a solution without side effects or use a traditional for loop.
If you are on Java 10, you can use var for that:
var ordinal = new Object() { int value; };
list.forEach(s -> {
s.setOrdinal(ordinal.value);
ordinal.value++;
});
You can wrap it up to workaround the compiler but please remember that side effects in lambdas are discouraged.
To quote the javadoc
Side-effects in behavioral parameters to stream operations are, in general, discouraged, as they can often lead to unwitting violations of the statelessness requirement
A small number of stream operations, such as forEach() and peek(), can operate only via side-effects; these should be used with care
I had a slightly different problem. Instead of incrementing a local variable in the forEach, I needed to assign an object to the local variable.
I solved this by defining a private inner domain class that wraps both the list I want to iterate over (countryList) and the output I hope to get from that list (foundCountry). Then using Java 8 "forEach", I iterate over the list field, and when the object I want is found, I assign that object to the output field. So this assigns a value to a field of the local variable, not changing the local variable itself. I believe that since the local variable itself is not changed, the compiler doesn't complain. I can then use the value that I captured in the output field, outside of the list.
Domain Object:
public class Country {
private int id;
private String countryName;
public Country(int id, String countryName){
this.id = id;
this.countryName = countryName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCountryName() {
return countryName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
}
Wrapper object:
private class CountryFound{
private final List<Country> countryList;
private Country foundCountry;
public CountryFound(List<Country> countryList, Country foundCountry){
this.countryList = countryList;
this.foundCountry = foundCountry;
}
public List<Country> getCountryList() {
return countryList;
}
public void setCountryList(List<Country> countryList) {
this.countryList = countryList;
}
public Country getFoundCountry() {
return foundCountry;
}
public void setFoundCountry(Country foundCountry) {
this.foundCountry = foundCountry;
}
}
Iterate operation:
int id = 5;
CountryFound countryFound = new CountryFound(countryList, null);
countryFound.getCountryList().forEach(c -> {
if(c.getId() == id){
countryFound.setFoundCountry(c);
}
});
System.out.println("Country found: " + countryFound.getFoundCountry().getCountryName());
You could remove the wrapper class method "setCountryList()" and make the field "countryList" final, but I did not get compilation errors leaving these details as-is.
To have a more general solution, you can write a generic Wrapper class:
public static class Wrapper<T> {
public T obj;
public Wrapper(T obj) { this.obj = obj; }
}
...
Wrapper<Integer> w = new Wrapper<>(0);
this.forEach(s -> {
s.setOrdinal(w.obj);
w.obj++;
});
(this is a variant of the solution given by Almir Campos).
In the specific case this is not a good solution, as Integer is worse than int for your purpose, anyway this solution is more general I think.

Why Java's Optional doesn't call Consumer in ifPresent()?

public class TestSupplier {
Optional<Integer> opt1;
public static void main(String[] args) {
// TODO Auto-generated method stub
TestSupplier ts1 = new TestSupplier();
ts1.opt1 = ts1.average(100,20,30,80);
Consumer<Integer> cns1 = (x) -> x += 3;
ts1.opt1.ifPresent(cns1);
System.out.println(ts1.opt1.get());
}
private Optional<Integer> average(int... n1) {
if (n1.length == 0) return Optional.empty();
int sum = 0;
for(int score: n1) sum += score;
return Optional.of(sum/n1.length);
}
}
when I run the code the result is 57 (that is the correct result of 100, 20, 30, 80 average) but I create a Consumer that should increment the result by 3... but it seems to not work.
Can someone help me?
The Consumer action is actually being run but the body you provided modifies only a local instance which eventually gets lost. The ifPresent() method should be used for performing side-effects(actions) only.
If you want to perform a calculation on a value held by an Optional instance, use map() instead.
ts1.opt1
.map(x -> x + 3).orElseThrow(...)
Remember to be careful when using get() on an Optional instance. Before you decide to use it, have a look at orElse, orElseGet, and orElseThrow.
Consumer<Integer> cns1 = new Consumer<Integer>() {
public #Override void accept(Integer x) {
// x is a local variable
x += 3; // unboxing, adding, boxing
// the local variable has been changed
}
};
It is that case when turning a lambda into an anonymous class perfectly makes this all clear to understand.
The best possible way here is
ts1.opt1.map(x -> x + 3).ifPresent(System.out::println);
You could use an instance of a mutable class (e.g. the AtomicInteger class):
Consumer<AtomicInteger> cns1 = x -> x.addAndGet(3);
which changes its state after accepting the Consumer<AtomicInteger> (although it is not recommended, look at #pivovarit's answer).
Furthermore, the line
IntStream.of(100, 20, 30, 80).average().ifPresent(System.out::println);
might replace all your routine work.

Is it possible to create in Java 8 a unlimitedly growing in lazy way collection, defined by recursion?

I can create a recursive closure:
static IntUnaryOperator fibo;
fibo =
(i) ->
i<2 ? 1 : fibo.applyAsInt(i-1)+ fibo.applyAsInt(i-2);
But of course, it has sense only as an example. To be useful, such collection should keep already once counted elements and get() them without recounting. The counting of elements should happen in lazy way, at first need. Thus, no member will have to be calculated more than once. In such way we'll a structure that will look like a recursively defined sequence, and will be fast and reusable.
When I started to study Java 8 I thought that Stream works in that way. But it does not, for the stream cannot be used twice.
I thought about the following construction:
IntStream fi;
fi=IntStream.iterate(0, i -> fi[i-1]+fi[i-2]);
But that way it won't work - I can't get an item from the stream by index.The other problem is that if I'll later go along the stream, it will be consumed and I can't use it repeatedly. If I copy the stream to List, it is not lazy anymore.
As a result, I need some construction that I can address by index. As fibo(i).
Edit. Obviously, the solution cannot be a stream, for the stream cannot be used twice. I don't want to repeat all calculations on every call to F(i).
It seems you are asking for something like this:
public class Fibonacci extends AbstractList<BigInteger> {
#Override
public Stream<BigInteger> stream() {
return Stream.iterate(new BigInteger[]{ BigInteger.ONE, BigInteger.ONE },
p->new BigInteger[]{ p[1], p[0].add(p[1]) }).map(p -> p[0]);
}
#Override
public Iterator<BigInteger> iterator() {
return stream().iterator();
}
#Override
public int size() {
return Integer.MAX_VALUE;
}
#Override
public BigInteger get(int index) {
return stream().skip(index).findFirst().get();
}
}
It’s accessible via the List interface (it doesn’t implement RandomAccess for a good reason), thus, you may ask for the n’th value via get(n). Note that the implementation of get hints how you can get values at positions after Integer.MAX_VALUE. Just use stream().skip(position).findFirst().get().
Beware! This list is infinite, as you asked for. Don’t ask it for things that operate on all elements, e.g. not even toString(). But things like the following will work smoothly:
System.out.println(new Fibonacci().subList(100, 120));
or
for(BigInteger value: new Fibonacci()) {
System.out.println(value);
if(someCondition()) break;
}
However, when you have to process large sequences of elements and want to do it efficiently, you should ensure to work on the iterator or stream to avoid O(n²) complexity of repeated get calls.
Note that I changed the element type to BigInteger as it would be pointless to think about infinite streams when it comes to the Fibonacci sequence and the int or long value type. Even with the long value type, the sequence is over after only 92 values as then, overflow occurs.
Update: now that you made clear that you are looking for a lazy storage, you may change the class above as follows:
public class Fibonacci extends AbstractList<BigInteger> {
final Map<BigInteger,BigInteger> values=new HashMap<>();
public Fibonacci() {
values.put(BigInteger.ONE, BigInteger.ONE);
values.put(BigInteger.ZERO, BigInteger.ONE);
}
#Override
public BigInteger get(int index) {
return get(BigInteger.valueOf(index));
}
public BigInteger get(BigInteger index) {
return values.computeIfAbsent(index, ix ->
get(ix=ix.subtract(BigInteger.ONE)).add(get(ix.subtract(BigInteger.ONE))));
}
#Override
public Stream<BigInteger> stream() {
return Stream.iterate(BigInteger.ZERO, i->i.add(BigInteger.ONE)).map(this::get);
}
#Override
public Iterator<BigInteger> iterator() {
return stream().iterator();
}
#Override
public int size() {
return Integer.MAX_VALUE;
}
}
I used BigInteger as key/index here to fulfill the requirement to be (theoretically) infinite, though we can use a long key as well for all practical uses. The key point is the initially empty storage: (now exemplary using long):
final Map<Long,BigInteger> values=new HashMap<>();
which is pre-initialized with the values that should end each recursion (unless it ends earlier due to already computed values):
values.put(1L, BigInteger.ONE);
values.put(0L, BigInteger.ONE);
Then, we can ask for a lazily computed value via:
public BigInteger get(long index) {
return values.computeIfAbsent(index, ix -> get(ix-1).add(get(ix-2)));
}
or a stream delegating to the get method described above:
LongStream.range(0, Long.MAX_VALUE).mapToObj(this::get);
This creates a stream that is only “practically infinite” whereas the complete example class above, using BigInteger is theoretically infinite…
The Map will remember every computed value of the sequence.
I cannot think up a good general solution, but if you want to access specifically two previous elements, this could be done in quite easy way defining the custom Spliterator like this:
public static IntStream iterate(int first, int second, IntBinaryOperator generator) {
Spliterator.OfInt spliterator = new AbstractIntSpliterator(Long.MAX_VALUE,
Spliterator.ORDERED) {
int prev1 = first, prev2 = second;
int pos = 0;
#Override
public boolean tryAdvance(IntConsumer action) {
if(pos < 2) {
action.accept(++pos == 1 ? prev1 : prev2);
} else {
int next = generator.applyAsInt(prev1, prev2);
prev1 = prev2;
prev2 = next;
action.accept(next);
}
return true;
}
};
return StreamSupport.intStream(spliterator, false);
}
Usage:
iterate(1, 1, Integer::sum).limit(20).forEach(System.out::println);
The solution will be created as a class FunctionalSequence for representation of a lazy, infinite sequence of objects, defined by a lambda function with integer argument. The function can be iterative or not. For the iterative case the FunctionalSequence class will have a method initialize for setting the start values.
The declaration of an object of such class will look so:
FunctionalSequence<BigInteger> fiboSequence = new FunctionalSequence<>();
fiboSequence.
initialize(Stream.of(BigInteger.ONE,BigInteger.ONE)).
setSequenceFunction(
(i) ->
fiboSequence.get(i-2).add(fiboSequence.get(i-1))
);
Notice, as in the recursive lambda example in the question, we cannot declare the object and define it recursively in one operator. One operator for declaration, another for definition.
The FunctionalSequence class definition:
import java.util.Iterator;
import java.util.LinkedList;
import java.util.stream.Stream;
public class FunctionalSequence<T> implements Iterable<T>{
LinkedList<CountedFlighweight<T>> realList = new LinkedList<>();
StackOverflowingFunction<Integer, T> calculate = null;
public FunctionalSequence<T> initialize(Stream<T> start){
start.forEachOrdered((T value) ->
{
realList.add(new CountedFlighweight<>());
realList.getLast().set(value);
});
return this;
}
public FunctionalSequence<T> setSequenceFunction(StackOverflowingFunction<Integer, T> calculate){
this.calculate = calculate;
return this;
}
#Override
public Iterator<T> iterator() {
return new SequenceIterator();
}
public T get(int currentIndex) throws StackOverflowError{
if(currentIndex < 0) return null;
while (currentIndex >= realList.size()){
realList.add(new CountedFlighweight<T>());
}
try {
return (T) realList.get(currentIndex).get(calculate, currentIndex);
} catch (Exception e) {
return null;
}
}
public class SequenceIterator implements Iterator<T>{
int currentIndex;
#Override
public boolean hasNext() {
return true;
}
#Override
public T next() {
T result = null;
if (currentIndex == realList.size()){
realList.add(new CountedFlighweight<T>());
}
// here the StackOverflowError catching is a pure formality, by next() we would never cause StackOverflow
try {
result = realList.get(currentIndex).get(calculate, currentIndex);
} catch (StackOverflowError e) {
}
currentIndex++;
return result;
}
}
/**
* if known is false, the value of reference is irrelevant
* if known is true, and reference is not null, reference contains the data
* if known is true, and reference is null, that means, that the appropriate data are corrupted in any way
* calculation on corrupted data should result in corrupted data.
* #author Pet
*
* #param <U>
*/
public class CountedFlighweight<U>{
private boolean known = false;
private U reference;
/**
* used for initial values setting
*/
private void set(U value){
reference = value;
known = true;
}
/**
* used for data retrieval or function counting and data saving if necessary
* #param calculate
* #param index
* #return
* #throws Exception
*/
public U get(StackOverflowingFunction<Integer, U> calculate, int index) throws StackOverflowError{
if (! known){
if(calculate == null) {
reference = null;
} else {
try {
reference = calculate.apply(index);
} catch (Exception e) {
reference = null;
}
}
}
known = true;
return reference;
}
}
#FunctionalInterface
public interface StackOverflowingFunction <K, U> {
public U apply(K index) throws StackOverflowError;
}
}
As the recursive function could easily meet the StackOverflowError, we should organize the recursion so that in that case the whole recursive sequence will roll back without any changes really met and throw the exception.
The use of the FunctionalSequence could look so:
// by iterator:
int index=0;
Iterator<BigInteger> iterator = fiboSequence.iterator();
while(index++<10){
System.out.println(iterator.next());
}
Or so:
static private void tryFibo(FunctionalSequence<BigInteger> fiboSequence, int i){
long startTime = System.nanoTime();
long endTime;
try {
fiboSequence.get(i);
endTime = System.nanoTime();
System.out.println("repeated timing for f("+i+")=" + (endTime-startTime)/1000000.+" ns");
} catch (StackOverflowError e) {
endTime = System.nanoTime();
//e.printStackTrace();
System.out.println("failed counting f("+i+"), time=" + (endTime-startTime)/1000000.+" ns");
}
}
The last function can be used in the following way:
tryFibo(fiboSequence, 1100);
tryFibo(fiboSequence, 100);
tryFibo(fiboSequence, 100);
tryFibo(fiboSequence, 200);
tryFibo(fiboSequence, 1100);
tryFibo(fiboSequence, 2100);
tryFibo(fiboSequence, 2100);
tryFibo(fiboSequence, 1100);
tryFibo(fiboSequence, 100);
tryFibo(fiboSequence, 100);
tryFibo(fiboSequence, 200);
tryFibo(fiboSequence, 1100);
Here are the results (the stack was limited to 256K for the needs of testing):
1
1
2
3
5
8
13
21
34
55
failed counting f(1100), time=3.555689 ns
repeated timing for f(100)=0.213156 ns
repeated timing for f(100)=0.002444 ns
repeated timing for f(200)=0.266933 ns
repeated timing for f(1100)=5.457956 ns
repeated timing for f(2100)=3.016445 ns
repeated timing for f(2100)=0.001467 ns
repeated timing for f(1100)=0.005378 ns
repeated timing for f(100)=0.002934 ns
repeated timing for f(100)=0.002445 ns
repeated timing for f(200)=0.002445 ns
repeated timing for f(1100)=0.003911 ns
Look, the repeatable call of the f(i) for the same index takes practically no time - no iterations were made. We cannot reach f(1100) at once because of the StackOverflowError. But after we have reached once f(200), f(1100) becomes reachable. We made it!

What's the best way to implement `next` and `previous` on an enum type?

Suppose I have an enum:
enum E {
A, B, C;
}
As shown in this answer by lucasmo, enum values are stored in a static array in the order that they are initialized, and you can later retrieve (a clone of) this array with E.values().
Now suppose I want to implement E#getNext and E#getPrevious such that all of the following expressions evaluate to true:
E.A.getNext() == E.B
E.B.getNext() == E.C
E.C.getNext() == E.A
E.A.getPrevious() == E.C
E.B.getPrevious() == E.A
E.C.getPrevious() == E.B
My current implementation for getNext is the following:
public E getNext() {
E[] e = E.values();
int i = 0;
for (; e[i] != this; i++)
;
i++;
i %= e.length;
return e[i];
}
and a similar method for getPrevious.
However, this code seems cumbersome at best (e.g., "empty" for loop, arguable abuse of a counter variable, and potentially erroneous at worst (thinking reflection, possibly).
What would be the best way to implement getNext and getPrevious methods for enum types in Java 7?
NOTE: I do not intend this question to be subjective. My request for the "best" implementation is shorthand for asking for the implementation that is the fastest, cleanest, and most maintainable.
Try this:
public enum A {
X, Y, Z;
private static final A[] vals = values();
public A next() {
return vals[(this.ordinal() + 1) % vals.length];
}
}
Implementation of previous() is left as an exercise, but recall that in Java, the modulo a % b can return a negative number.
EDIT: As suggested, make a private static copy of the values() array to avoid array copying each time next() or previous() is called.
Alternatively, one can go somehow along the lines of the following idea:
public enum SomeEnum {
A, B, C;
public Optional<SomeEnum> next() {
switch (this) {
case A: return Optional.of(B);
case B: return Optional.of(C);
// any other case can NOT be mapped!
default: return Optional.empty();
}
}
Notes:
In contrast to the other answer, this way does some implicit mapping; instead of relying on ordinal(). Of course that means more code; but it also forces the author to consider what it means to add new constants or remove existing ones. When relying on ordinal, your implicit assumption is that the order is based on the order used for the enum constant declaration. So when somebody comes back 6 months later and has to add a new constant, he has to understand that the new constant Y needs X, Y, Z ... instead of just appending X, Z, Y!
There might be situations where it doesn't make any sense for the "last" enum constant to have the "first" as successor. Think of T-Shirt sizes for examples. XXL.next() is for sure not XS. For such situations, using Optional is the more appropriate answer.
public enum Three
{
One, Two, Three;
static
public final Three[] values = values();
public Three prev() {
return values[(ordinal() - 1 + values.length) % values.length];
}
public Three next() {
return values[(ordinal() + 1) % values.length];
}
}
Here's another take at the problem:
public enum Planet {
MERCURY, VENUS, EARTH, MARS, JUPITER, SATURN, URANUS, NEPTUNE;
private Planet prevPlanet = null;
private Planet nextPlanet = null;
static {
for (int i = 1; i <= values.length; i++) {
Planet current = values[i % values.length];
current.prevPlanet = values[i - 1];
current.nextPlanet = values[(i + 1) % values.length];
}
}
public Planet prev() {
return prevPlanet;
}
public Planet next() {
return nextPlanet;
}
}
With this approach, all calculations are done during static initialization and the actual methods directly return the result from a member variable.
However, I would argue that for this enum (and for most enums in general), wrapping around doesn't make sense, so I would rather do it this way:
import java.util.Optional;
public enum Planet {
MERCURY, VENUS, EARTH, MARS, JUPITER, SATURN, URANUS, NEPTUNE;
private Planet prevPlanet = null;
private Planet nextPlanet = null;
static {
Planet[] values = Planet.values();
for (int i = 1; i < values.length; i++) {
values[i].prevPlanet = values[i - 1];
}
for (int i = 0; i < values.length - 1; i++) {
values[i].nextPlanet = values[i + 1];
}
}
public Optional<Planet> prev() {
return Optional.ofNullable(prevPlanet);
}
public Optional<Planet> next() {
return Optional.ofNullable(nextPlanet);
}
}
Here, the first planet does not have a previous one and the last one does not have a next one. Optional is used to make it even more explicit that callers of the code need to be prepared that not every planet has a next/previous one. Whether you want to use Optional is up to you, the code works just as well with the getters of the first implementation, in which case a null would be returned directly instead of as an empty Optional.
Another thing to consider is that the desired ordering may not match the enumeration of the values. There could also be special values in the enum that do not fit in the ordering. Or you could just want to make the specification of the ordering explicit so that one can not accidentally break the logic by adding a new value to the enum out of order. Then you can do this:
import java.util.Optional;
public enum Planet {
MERCURY, VENUS(MERCURY), EARTH(VENUS), MARS(EARTH), JUPITER(MARS),
SATURN(JUPITER), URANUS(SATURN), NEPTUNE(URANUS);
private Planet prevPlanet = null;
private Planet nextPlanet = null;
Planet() {}
Planet(Planet prev) {
this.prevPlanet = prev;
prev.nextPlanet = this;
}
public Optional<Planet> prev() {
return Optional.ofNullable(prevPlanet);
}
public Optional<Planet> next() {
return Optional.ofNullable(nextPlanet);
}
}
This doesn't allow for wraparounds, but you could use this as a low-impact way to check adjacency:
enum Phase {
ONE, TWO, THREE;
public final Phase previous;
Phase() {
previous = Data.last;
Data.last = this
}
private static class Data {
private static Phase last = null;
}
}
class Example {
Phase currentPhase = Phase.ONE;
void advanceToPhase(Phase nextPhase) {
if (nextPhase.previous == currentPhase)
currentPhase = nextPhase;
}
}
It has to use an auxiliary static class to store a variable for the static initializer, but it has the advantage of being extremely low-cost at startup.
Same approach as #Zoltan but without optional :
public enum Planet {
MERCURY, VENUS(MERCURY), EARTH(VENUS), MARS(EARTH), JUPITER(MARS),
SATURN(JUPITER), URANUS(SATURN), NEPTUNE(URANUS);
private Planet prevPlanet = null;
private Planet nextPlanet = null;
Planet() {
// required for Mercury
}
Planet(Planet prev) {
prevPlanet = prev;
prev.nextPlanet = this;
}
public Planet prev() {
return this == MERCURY ? this : prevPlanet;
}
public Planet next() {
return this == NEPTUNE ? this : nextPlanet;
}
}
TreeSet-based implementation
We can implement an enum capable of retrieving next and previous members via instance methods next() and previous() by using TreeSet, which maintains a Red-black tree under the hood, and offers methods for traversing the tree like higher() and lower().
The implementation below would in a way similar to a circular list, retrieving the fist enum-constant when next() is invoked on the very last constant, and vice versa returning the last when previous() is called on the very first constant.
Instead of hard-coding the fist and the last enum-members inside the next() and previous() when we hit edge-cases, we can use methods first() and last(). By doing so, we're eliminating the possibility of introducing a bug, if someone would decide to add a few more constants or reorder them.
public enum Enum {
A, B, C, D, E, F, G;
private static final NavigableSet<Enum> set =
new TreeSet<>(EnumSet.allOf(Enum.class)); // EnumSet.allOf() generates a set of enum-constants of the specified type
public Enum next() {
return Objects.requireNonNullElseGet(
set.higher(this), set::first
);
}
public Enum previous() {
return Objects.requireNonNullElseGet(
set.lower(this), set::last
);
}
}
Note: both higher() and lower() would return null if the requested element doesn't exist. To dial with the edge-cases I've used Java 11 utility method Objects.requireNonNullElseGet() which expects a nullable value and a Supplier that would be used only if provided value is null (reminder: Java 8 functions are lazy).
main()
public static void main(String[] args) {
EnumSet.allOf(Enum.class).forEach(e ->
System.out.println(e + " -> " + " next: " + e.next() + " prev: " + e.previous())
);
}
Output:
A -> next: B prev: G
B -> next: C prev: A
C -> next: D prev: B
D -> next: E prev: C
E -> next: F prev: D
F -> next: G prev: E
G -> next: A prev: F
Performance Note
All the methods of the TreeSet used above have logarithmic time complexity O(log n), which in most of the real life scenarios would result in only a couple of steps through the tree, since the waste majority of enums have fewer than ten constants. Therefore, we can call it acceptable, but it can't beat constant time the performance of the straightforward solution provided in the answer by Jim Garrison.
That said, the code above is meant to serve educational purposes by illustrating how a TreeSet can be utilized.

java retain information in recursive function

Is it possible to retain information via a helper function with java, without using static variables.
For example,
public void foo(){
int v = 0;
fooHelper(2);
}
public void fooHelper(int depth){
v++;
fooHelper(depth-1)
}
Namely I want to update variable v without loosing the information for each recursive case, without having to access a variable outside the function.
Forget about all the answers that tell you to declare attributes, or to update mutable objects in each recursive call. In a true functional, recursive style you "retain" information by passing it as parameters and/or return types.
Let me illustrate with a simple example, let's say that you want to recursively calculate the sum of the elements in an int[]. Here, the state (the information that needs to be retained between recursive calls) is the current index in the array and the sum so far. Here's how to do it:
public int sum(int[] array) {
return sum(array, 0, 0);
}
private int sum(int[] array, int idx, int acc) {
if (idx == array.length)
return acc;
return sum(array, idx+1, acc+array[idx]);
}
Call it like this:
int[] array = {1, 2, 3};
System.out.println(sum(array));
As you can see, there's no need to declare (static or instance) attributes, and no need to pass and modify mutable objects (lists, maps) - I'm not even using local variables, because all the required information needed to solve the problem is present as method parameters.
In the code in your question the v variable is supposed to do what the acc parameter is doing in my answer, namely: modifying an accumulated value each time the recursion is called. In the end, you just need to return the accumulated value from the helper function (which must not have a void return type) and that's how you'll get the value in foo().
A variable declared in a scope (for example method) is accessible only in this scope (e.g. not in another method).
If the information is relevant for the method only, keep the variable in the method. If the information is relevant for the whole object / class state, keep it a class member (static/non static).
For example:
public void someRecursiveMethod(int num) {
while (num < 10) {
num++;
someRecursiveMethod(num);
System.out.println("Current num = " + num);
}
}
You can create a new class (yuck), or pass the variable as a parameter and return it in fooHelper.
Why not make it an instance variable(not necessarily static)...??
public class Recursive {
int v = 0;
public void foo(){
fooHelper(2);
System.out.println(v);
}
public void fooHelper(int depth){
v++;
if(depth-1!=0)//Added this because I was getting an StackOverflowError
fooHelper(depth-1);
}
public static void main(String[] args) {
Recursive r = new Recursive();
r.foo();
}
}
You could return a list or a similar data structure:
public List<Integer> fooHelper( int v, int depth ){
if( depth == 0 ) return new ArrayList();
v++;
List<Integer> result = fooHelper( v, depth-1 );
result.add( new Integer(v) );
return result;
}
Because the variable v is of primitive type, changes made to it will not be visible outside the function scope. You could declare the variable v inside a class, say State and pass the state object into the recursive function to get the required effect.
public void foo(){
State state = new State();
fooHelper(state, 2);
}
public void fooHelper(State state, int depth){
state.v++;
fooHelper(state, depth-1);
}
class State {
int v;
}
Hope it helps.
You can pass an object to store the update for each recursive call. Something like the one below.
public static void fooHelper(int depth, HashMap map){
map.put(depth, "Call " + depth);
if (depth > 0)
{
fooHelper(depth-1, map);
}
return;
}
I think this is called memoization. It looks like
class Fibonacci
{
public Map < Integer , Integer > memorized = new HashMap < > ( ) ;
public int fib ( int n )
{
if ( memoized . containsKey ( n ) )
{
return memoized . get ( n ) ;
}
else
{
int fib = // calculate recursively
memoized . put ( n , fib ) ;
return fib ;
}
}
}
You should be able to get decent (not optimal) performance out of this algorithm. The primary reason that the recursive fibonacci algorithm has horrible performance is b/c it is repeatedly calculating the same values. With recursion+memoization it never calculates any value more than once.
Thanks to #Aristide for pointing out the subtle difference between memorization and memoization.

Categories