Java 8 variable should be final or effectively final issue [duplicate] - java

This question already has answers here:
Variable used in lambda expression should be final or effectively final
(9 answers)
Closed 1 year ago.
I am using Java 8 stream Iteration with a variable that should be used in other classes also. So I have used the below code.
AtomicBoolean bool = new AtomicBoolean(true);
public void testBool(){
list.stream().forEach(c->{
if( c.getName() != null){
bool.set(true);
}
});
}
public void test(){
if(bool.get()){
System.out.println("value is there");
}
}
But I heard like using the Atomic Object will be a performance hit sometimes. Is there any alternate approach to use the variables outside the forEach block with Java 8 usage?
Without this am getting the error as a variable should be a final or effectively final error.
Please help me to resolve this issue.
Thanks in advance.

You could avoid the problem by using the lambda expression to return true or false if there are any names that are not null, and assign the result to your boolean.
Something like this:
boolean hasAnyWithNames = list.stream().anyMatch(c -> c.getName() != null);
The choice "bool" is not a good one for variable name by the way.
Edit:
Replaced Boolean with base type per comment.
Used anyMatch() instead of filter() count per comment
Thanks

The effectively final restriction only applies to local variables.
Since you are setting an instance field, you can simply use:
boolean bool = true; and set it from within the lambda.
If you need to use a local variable, add the final modifier to the declaration.
Regarding the overhead of using AtomicBoolean, keep in mind that streams also have overhead and if you're only using them for iteration you're better off using a for loop instead:
boolean bool = true;
public void testBool(){
for (var c : list) {
if (c.getName() != null) {
bool = true;
break;
}
}
}
Lastly, as #Neela mentioned in a comment, a more efficient use of streams would be with the following code*:
boolean bool = list.stream().anyMatch(c -> c.getName() != null);
*Note, the original code has an error that results in bool always being true and this is avoided by not presetting true and directly putting the result of anyMatch.

Related

Java Lambda style

So, this doesn't work, since seatsAvailable is final. How can what I'm trying to accomplish be done using more of a lambda-style-from-the-ground-up way?
final boolean seatsAvailable = false;
theatreSeats.forEach(seat -> {
if (!seatsAvailable) seatsAvailable = seat.isEmpty();
});
It looks like you want seatsAvailable to be true if there is at least one empty seat. Therefore, this should do the trick for you:
final boolean seatsAvailable = theatreSeats.stream().anyMatch(Seat::isEmpty);
(Note: I am assuming that your class is named Seat.)

Omitting an instance field at run time in Java

Java's assert mechanism allows disabling putting in assertions which have essentially no run time cost (aside from a bigger class file) if assertions are disabled. But this may cover all situations.
For instance, many of Java's collections feature "fail-fast" iterators that attempt to detect when you're using them in a thread-unsafe way. But this requires both the collection and the iterator itself to maintain extra state that would not be needed if these checks weren't there.
Suppose someone wanted to do something similar, but allow the checks to be disabled and if they are disabled, it saves a few bytes in the iterator and likewise a few more bytes in the ArrayList, or whatever.
Alternatively, suppose we're doing some sort of object pooling that we want to be able to turn on and off at runtime; when it's off, it should just use Java's garbage collection and take no room for reference counts, like this (note that the code as written is very broken):
class MyClass {
static final boolean useRefCounts = my.global.Utils.useRefCounts();
static {
if(useRefCounts)
int refCount; // want instance field, not local variable
}
void incrementRefCount(){
if(useRefCounts) refCount++; // only use field if it exists;
}
/**return true if ready to be collected and reused*/
boolean decrementAndTestRefCount(){
// rely on Java's garbage collector if ref counting is disabled.
return useRefCounts && --refCount == 0;
}
}
The trouble with the above code is that the static bock makes no sense. But is there some trick using low-powered magic to make something along these lines work? (If high powered magic is allowed, the nuclear option is generate two versions of MyClass and arrange to put the correct one on the class path at start time.)
NOTE: You might not need to do this at all. The JIT is very good at inlining constants known at runtime especially boolean and optimising away the code which isn't used.
The int field is not ideal, however, if you are using a 64 bit JVM, the object size might not change.
On the OpenJDK/Oracle JVM (64-bit), the header is 12 bytes by default. The object alignment is 8 byte so the object will use 16 bytes. The field, adds 4 bytes, which after alignment is also 16 bytes.
To answer the question, you need two classes (unless you use generated code or hacks)
class MyClass {
static final boolean useRefCounts = my.global.Utils.useRefCounts();
public static MyClass create() {
return useRefCounts ? new MyClassPlus() : new MyClass();
}
void incrementRefCount() {
}
boolean decrementAndTestRefCount() {
return false;
}
}
class MyClassPlus extends MyClass {
int refCount; // want instance field, not local variable
void incrementRefCount() {
refCount++; // only use field if it exists;
}
boolean decrementAndTestRefCount() {
return --refCount == 0;
}
}
If you accept a slightly higher overhead in the case you’re using your ref count, you may resort to external storage, i.e.
class MyClass {
static final WeakHashMap<MyClass,Integer> REF_COUNTS
= my.global.Utils.useRefCounts()? new WeakHashMap<>(): null;
void incrementRefCount() {
if(REF_COUNTS != null) REF_COUNTS.merge(this, 1, Integer::sum);
}
/**return true if ready to be collected and reused*/
boolean decrementAndTestRefCount() {
return REF_COUNTS != null
&& REF_COUNTS.compute(this, (me, i) -> --i == 0? null: i) == null;
}
}
There is a behavioral difference for the case that someone invokes decrementAndTestRefCount() more often than incrementRefCount(). While your original code silently runs into a negative ref count, this code will throw a NullPointerException. I prefer failing with an exception in this case…
The code above will leave you with the overhead of a single static field in case you’re not using the feature. Most JVMs should have no problems eliminating the conditionals regarding the state of a static final variable.
Note further that the code allows MyClass instances to get garbage collected while having a non-zero ref count, just like when it was an instance field, but also actively removes the mapping when the count reaches the initial state of zero again, to minimize the work needed for cleanup.

How to avoid checking for null values in method chaining? [duplicate]

This question already has answers here:
Null check chain vs catching NullPointerException
(19 answers)
Avoiding NullPointerException in Java
(66 answers)
Closed 4 years ago.
I need to check if some value is null or not. And if its not null then just set some variable to true. There is no else statement here. I got too many condition checks like this.
Is there any way to handle this null checks without checking all method return values?
if(country != null && country.getCity() != null && country.getCity().getSchool() != null && country.getCity().getSchool().getStudent() != null .....) {
isValid = true;
}
I thought about directly checking variable and ignoring NullpointerException. Is this a good practice?
try{
if(country.getCity().getSchool().getStudent().getInfo().... != null)
} catch(NullPointerException ex){
//dont do anything.
}
No, it is generally not good practice in Java to catch a NPE instead of null-checking your references.
You can use Optional for this kind of thing if you prefer:
if (Optional.ofNullable(country)
.map(Country::getCity)
.map(City::getSchool)
.map(School::getStudent)
.isPresent()) {
isValid = true;
}
or simply
boolean isValid = Optional.ofNullable(country)
.map(Country::getCity)
.map(City::getSchool)
.map(School::getStudent)
.isPresent();
if that is all that isValid is supposed to be checking.
You could use Optional here, but it creates one Optional object at each step.
boolean isValid = Optional.ofNullable(country)
.map(country -> country.getCity()) //Or use method reference Country::getCity
.map(city -> city.getSchool())
.map(school -> school.getStudent())
.map(student -> true)
.orElse(false);
//OR
boolean isValid = Optional.ofNullable(country)
.map(..)
....
.isPresent();
The object-oriented approach is to put the isValid method in Country and the other classes. It does not reduce the amount of null checks, but each method only has one and you don't repeat them.
public boolean isValid() {
return city != null && city.isValid();
}
This has the assumption that validation is the same everywhere your Country is used, but typically that is the case. If not, the method should be named hasStudent(), but this is less general and you run the risk of duplicating the whole School interface in Country. For example, in another place you may need hasTeacher() or hasCourse().
Another approach is to use null objects:
public class Country {
public static final Country NO_COUNTRY = new Country();
private City city = City.NO_CITY;
// etc.
}
I'm not sure it is preferable is this case (strictly you would need a sub class to override all modification methods), the Java 8 way would be to go with Optional as method in the other answers, but I would suggest to embrace it more fully:
private Optional<City> city = Optional.ofNullable(city);
public Optional<City> getCity() {
return city;
}
Both for null objects and Nullable only work if you always use them instead of null (notice the field initialization), otherwise you still need the null checks. So this option avoid null, but you code becomes more verbose to reduced null checks in other places.
Of course, the correct design may be to use Collections where possible (instead of Optional). A Country has a set of City, City has a set of Schools, which has set of students, etc.
As alternative to other fine usage of Optional, we could also use a utility method with a Supplier<Object> var-args as parameter.
It makes sense as we don't have many nested levels in the object to check but many fields to check.
Besides, it may easily be modified to log/handle something as a null is detected.
boolean isValid = isValid(() -> address, // first level
() -> address.getCity(), // second level
() -> address.getCountry(),// second level
() -> address.getStreet(), // second level
() -> address.getZip(), // second level
() -> address.getCountry() // third level
.getISO()
#SafeVarargs
public static boolean isValid(Supplier<Object>... suppliers) {
for (Supplier<Object> supplier : suppliers) {
if (Objects.isNull(supplier.get())) {
// log, handle specific thing if required
return false;
}
}
return true;
}
Suppose you would like to add some traces, you could so write :
boolean isValid = isValid( Arrays.asList("address", "city", "country",
"street", "zip", "Country ISO"),
() -> address, // first level
() -> address.getCity(), // second level
() -> address.getCountry(),// second level
() -> address.getStreet(), // second level
() -> address.getZip(), // second level
() -> address.getCountry() // third level
.getISO()
);
#SafeVarargs
public static boolean isValid(List<String> fieldNames, Supplier<Object>... suppliers) {
if (fieldNames.size() != suppliers.length){
throw new IllegalArgumentException("...");
}
for (int i = 0; i < suppliers.length; i++) {
if (Objects.isNull(suppliers.get(i).get())) {
LOGGER.info( fieldNames.get(i) + " is null");
return false;
}
}
return true;
}
Java doesn't have "null-safe" operations, like, for example Kotlin's null safety
You can either:
catch the NPE and ignore it
check all the references manually
use Optional as per the other answers
use some sort of tooling like XLST
Otherwise if you have control over the domain objects, you can redesign your classes so that the information you need is available from the top level object (make Country class do all the null checking...)
You could also look at vavr's Option which as the below posts describes is better than Java's Optional and has a much richer API.
https://softwaremill.com/do-we-have-better-option-here/

Which is the best way to set/drop boolean flag inside lambda function

Say I have a currency rates loader returning isLoaded=true result only when all the rates are loaded successfully:
//List<String> listFrom = Stream.of("EUR", "RUB").collect(toList());
//List<String> listTo = Stream.of("EUR", "CNY").collect(toList());
boolean isLoaded = true;
final FixerDataProvider httpProvider = new FixerDataProvider(maxAttempts);
final List<CurrencyRatePair> data =
listFrom.stream()
.flatMap(from -> {
final List<CurrencyRatePair> result = httpProvider.findRatesBetweenCurrencies(from, listTo);
if (Objects.isNull(result) || result.size() == 0) {
isLoaded = false; //!!!Not working as ineffectively final!!!
}
return result.stream();
}).collect(Collectors.toList());
if (!isLoaded) {
return false;
}
// do smth with loaded data
return true;
Assignment isLoaded = false; inside lambda function is not allowed when isLoaded variable is not final or effectively final.
Which is the most elegant solution to set/drop boolean flag inside lambda expressions?
What do you think about AtomicBoolean and set(false) method as a possible approach?
You may be better off with an old-style loop, as others have suggested. It does feel like a bit of a programming faux pas to write lambdas with side-effects, but you're likely to find an equal number of developers who think it's fine too.
As for getting this particular lambda-with-side effects working, making isLoaded into an AtomicBoolean is probably your best bet. You could achieve the same effect by making isLoaded a boolean[] of size 1, but that seems less elegant than going with AtomicBoolean to me.
But seriously, try using an old-school loop instead too and see which one you like better.
If you use parallel stream, you must use AtomicBoolean. Because boolean[1] may not be safe in parallel scenario.
The java.util.stream javadoc states that
Side-effects in behavioral parameters to stream operations are, in general, discouraged, as they can often lead to unwitting violations of the statelessness requirement, as well as other thread-safety hazards.
That said, if you want to do it anyway, the solution you have identified with an AtomicBoolean will do the trick just fine.
Variables used within anonymous inner classes and lambda expression have to be effectively final.
You can use AtomicReference for your case, here is a similar snippet from ConditionEvaluationListenerJava8Test
public void expectedMatchMessageForAssertionConditionsWhenUsingLambdasWithoutAlias() {
final AtomicReference<String> lastMatchMessage = new AtomicReference<>();
CountDown countDown = new CountDown(10);
with()
.conditionEvaluationListener(condition -> {
try {
countDown.call();
} catch (Exception e) {
throw new RuntimeException(e);
}
lastMatchMessage.set(condition.getDescription());
})
.until(() -> assertEquals(5, (int) countDown.get()));
String expectedMatchMessage = String.format("%s reached its end value", CountDown.class.getName());
assertThat(lastMatchMessage.get(), allOf(startsWith("Condition defined as a lambda expression"), endsWith(expectedMatchMessage)));
}
Cheers !
If I right understand you will get isLoaded=false only in case if all off result lists will be empty (If result list is null you will get NPE in the next line so there is no any reason to do null check in this way). In this case your data list also will be empty and you don't need any boolean flags, just check if data.isEmpty() and return false if true.

using an array for a switch case statement in java

I'm making a game, and i want the controls to be editable. well, i've got that part down, but they are being read and changed in a .txt file. that is the way i wanted it to work for now. the values are stored as the key value (ie. KeyEvent.VK_W is equal to 83, so the value for the line is 83). I also have it reading the values and saving them to a String array variable in my core class. In my key event class, the one that handles the pushing of the keys, i have it refering to the array to check if a command key was pushed. i'm continuously getting this error: case expressions must be constant expressions when i try it. here is the WRONG code:
switch(key){
case Integer.parseInt(commands[1]):
...
break;
}
and i get that error. the value of commands[1] is 83. it is the value for "W". here is my declaration of the variable:
for (int i = 0; i < commands.length; i++) {
commands[i] = io.readSpecificLine(FILES.controlsFileFinalDir,
i + 1);
}
and if i have it print out every value, it does work. i've tried making the array final but that didnt work. i've run across the solution before, about 2 years ago, but i cant find it again. does anyone have any ideas on how to fix this? thanks in advance!
As the compiler says, the case expressions must be constant expressions. You can't use an array element as a case expression. You can simply use an if/else if/else clause instead.
You can't use non-constant expressions in case statements. An alternative approach is to build a map from values to the actions. So instead of this (which doesn't actually make any sense to me):
switch (key) {
case Integer.parseInt(commands[1]):
// action 1
break;
// other cases...
default:
// default action
}
You can do something like this:
static Map<Integer, Runnable> keyMap = new HashMap<Integer, Runnable>();
static {
keyMap.put(83, new Runnable() {
#Override
public void run() {
// actions for code 83
}
});
. . .
}
(If it makes more sense, this could also be done on a per-instance basis instead of as a static map.) Then later:
Runnable action = keyMap.get(Integer.parseInt(commands[1]));
if (action != null) {
action.run();
} else {
// default action
}
If you need to pass variables to your actions, you can define your own interface instead of using Runnable for the actions.

Categories