Lambda functions with Optional instead of nested if else [closed] - java

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 1 year ago.
Improve this question
Optional<String> myData;
Set<String> mySet;
if(myData.isPresent()) {
if(myData.get().contains(“testValue”)) {
mySet.add(“somedata”);
}
}
if(!myData.isPresent()) {
mySet.add(“someotherdata”);
}
I have a scenario like this. Where I have nested if-else block and I need to convert that into Java8 map using lambda functions. How can I do that?

This will reproduce your earlier results but has been slightly altered. I believe that a stream solution is not necessary nor desirable. The following will:
result in an empty set if data is present but not testValue
result in the set containing someotherdata if the data is not present
result in the set containing somedata if the data is present and matches testValue
String result = myData.isPresent() ?
(myData.get().contains("testValue") ? "somedata" : "") :
"someotherdata";
if (!result.isBlank()) {
mySet.add(result);
}

You could rework your Optional use (this only apply to your code, as originally presented [in case you edit it]):
Optional<String> myData = ...;
myData.ifPresent(value -> {
if (value.contains("testValue")) {
mySet.add("somedata"),
}
});
if (!myData.isPresent()) {
mySet.add("someotherdata");
}
If you are using Java 11, you should use:
myData.ifPresentOrElse(
value -> {
if (value.contains("testValue")) {
mySet.add("somedata");
}
},
() -> mySet.add("someotherdata")
);
It is up to you to decide which is better (the first avoid doing mySet.add twice in two part).
[edit] fixed the answer and compilation issues per comment remark.

You can use filter to avoid the nested logic in the present case. Your second case has no nested logic, seems fine as is.
myData.filter(d -> d.contains("testValue"))
.ifPresent(mySet::add);
if(!myData.isPresent()) {
mySet.add(“someotherdata”);
}

Well, if you insist:
Optional<String> myData = Optional.of("x");
Set<String> mySet = myData
.<Set<String>>map(s -> s.contains("testValue") ? Set.of("somedata") : Set.of())
.orElse(Set.of("someotherdata"));
System.out.println(mySet);
Output in this case:
[]
Testing other optionals:
Optional<String> myData = Optional.of("x testValue x");
[somedata]
Optional<String> myData = Optional.empty();
[someotherdata]
My own preference is for the use of ifPresentOrElse() shown in the last half of the answer by NoDataFound.

Related

How to print List of String array array using lambda in Java [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 1 year ago.
Improve this question
This is my code:
List<String[]> salaries = getSalariesByMonth();
//I am using the old way to print the data
for (String[] obj : rates) {
System.out.println("User name: "obj[0]+"--"+"Salary: "+obj[1]); //obj[0] is NAME, obj[1] is SALARY
}
//I am trying to use this way to print the data but unable to do so.
salaries.forEach(s-> System.out.println("print NAME and SALARY"));
How to print the List that contains String array using Lambda. Thank you in advance.
To convert a for-each loop into a forEach call the general pattern is:
for (final var x : xs) {
statements;
}
// becomes:
xs.forEach(x -> { statements; });
// with a single statement, braces are optional:
xs.forEach(x -> statement);
A lambda of the form (x, y) -> { statements; } is mostly equivalent to a method of the form:
… yourMethod(final … x, final … y) {
statements;
}
Return type and parameter type are inferred automatically by the compiler when a lambda is encountered.
So in your case that would be:
salaries.forEach(obj -> System.out.println("User name: "+obj[0]+"--"+"Salary: "+obj[1]));
You could also use streams to first map each object to a string representation and then output each item in a terminal operation:
salaries.stream()
.map(obj -> "User name: "+obj[0]+"--"+"Salary: "+obj[1])
.forEach(s -> System.out.println(s));
Since System.out.println expects exactly one argument which matches the lambda argument, it could be replaced with a method reference, which can be more readable in some cases: .forEach(System.out::println)
salaries.stream()
.map(salary -> String.format("User name: %s -- Salary: %s", salary[0], salary[1]))
.forEach(System.out::println);

Create new Objects based on a String with Java Stream [closed]

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 3 years ago.
Improve this question
i m playing around with Java Streams and I wonder if there is any way to create a code Block like this ->
if(givenString.equals("productA")) {
return new productA();
} else if(givenString.equals("productB") {
return new productB();
} .....
into a Java Stream like this ->
Stream.of(givenString)
.filter(e -> e.equal("productA)")
.map(e -> new productA())
i came across with this solution which works but i m not convinced...
Stream.of(givenString)
.map(e -> e -> e.equals("productA)" ? new productA() : new productB())
.findAny()
.get()
You don't want to do that inline in a stream. Instead, write a helper method that does just that:
private static Product createByString(String name) {
// I assume Product is a common superclass
// TODO: implement
}
Now the question is: How should this method be implemented?
Use a big switch statement.
private static Product createByString(String name) {
switch (name) {
case "productA": new productA();
case "productB": new productB();
// ... maybe more?
default: throw new IllegalArgumentException("name " + name + " is not a valid Product");
}
}
Pro: a switch on a string is compiled into a jumptable, so you won't have n string comparisons.
Con: You can't extend it at runtime, and you have to keep this method in sync.
Use a HashMap<String,Supplier<Product>>.
private static final Map<String,Supplier<Product>> productConstructors = new HashMap<>();
static {
productConstructors.put("productA", productA::new);
productConstructors.put("productB", productB::new);
}
private static Product createByString(String name) {
Supplier<Product> constructor = productConstructors.get(name);
if (constructor == null) {
// Handle this?
throw new IllegalArgumentException("name " + name + " is not a valid Product");
}
return constructor.get();
}
Pro: with some easy modifications you can add new products to this implementation, or even replace them.
Con: has some moderate overhead, and you still need to maintain a the mapping between "productA" and it's type.
Use reflection.
The good old hammer where every problem looks like a nail.
private static Product createByString(String name) {
try {
return Class.forName("your.pkgname. " + name).asSubclass(Product.class).getConstructor().newInstance();
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
Pro: You don't need to do the binding.
Con: It's slow.
In your first example below:
if(givenString.equals("productA")) {
return new productA();
} else if(givenString.equals("productB") {
return new productB();
}
You are returning an instance of some object specified via a string. It seems to me that if you know the string, you can just create the object right away without using an intervening method call to do so.
Another possibility is that the class name was provided via some user input. In this case you might want to consider reflection to accomplish this so you can reference the methods and fields of the newly created class.
In either case I doubt streams is a reasonable approach for this sort of requirement.

Conditional Logic to Determine Correct Status String [closed]

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 4 years ago.
Improve this question
There is a status variable in a Java application that can be set to one of many statutes, depending on many conditions. The status field is a String. When a condition is met, the status should be returned immediately, as follows:
e.g
String status = "";
if (condition1) {
return "STATUS_1";
} else if (condition2) {
return "STATUS_2";
} else if (condition3) {
return "STATUS_3";
} else if (condition4) {
return "STATUS_4";
}
...
else if (condition10) {
return "STATUS_10";
}
I've considered which pattern would be best to make this code more SOLID... e.g. if a new condition is required then this class would need to edited to add the new condition, which would break the open / closed SOLID principle
I've looked at the Strategy Pattern, in particular "Replace Conditional Logic with Strategy", however that seems more appropriate when you want to decide on just one calculation / operation to use... My scenario does not seem to fit the Strategy Pattern as my logic determines the status, rather than determining which individual operation to execute - I need to run all the conditions until one is true
I wondered if the following pattern could work...
Have an interface as follows
public interace StatusCondition {
boolean condition(Context context);
String getStatus();
}
With an implementation as follows:
public class StatusAStatusCondition implements StatusCondition {
boolean condition(Context context){
return context.getValue1() == 0 && context.getValue2().equals("A");
}
String getStatus(){
return "STATUS_A";
}
}
This would allow a list of StatusCondition classes to be executed in order and return the status of the first StatusCondition where the condition() method returns true. e.g:
public String getStatus(List<StatusCondition> statusConditions) {
for (StatusCondition statusCondition : statusConditions) {
if (statusCondition.condition()) {
return statusCondition.getStatus();
}
}
return "";
}
usage:
List<StatusCondition> statusConditions = new ArrayList<>();
statusConditions.add(statusAStatusCondition);
statusConditions.add(statusBStatusCondition);
statusConditions.add(statusCStatusCondition);
statusConditions.add(statusDStatusCondition);
statusConditions.add(statusEStatusCondition);
statusConditions.add(statusFStatusCondition);
...
String status = getStatus(statusConditions);
To me this solves the open closed principle issue and also ensures the implementations are single responsibility... My question is, how could this pattern i've suggested be improved, or is there a pattern better suited to my scenario?
First, you are absolutely correct that the original if/else ladder violates the Open/Closed Principle. Second, converting the status value to an interface is exactly the right step to take, to move away from stringly-typed programming. Third, your solution is essentially the Chain of Responsibility Pattern. It's an excellent solution to this problem. In summary, your instincts are spot on.

Cannot remove element from an Array List [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 4 years ago.
Improve this question
Some background: I am new to Java and am taking a basic java class. I am currently on the final project for the class and completed everything except for this last bit of code. For some reason, I am having the toughest time deleting an element from an array list. Here is the code I am working on:
public static void delete(String bookID) {
for (book eachElement : catalog) {
if (eachElement.getBookID().equals(bookID)) {
catalog.remove(eachElement);
return;
}
}
}
code executes, no run time errors but it won't delete anything.
also, I know everything works prior to the remove statement because I have another method that computes calculations using the same exact for and if statement with a select bookID string.
You should not and cannot remove an Element from a Collection while being in a forEach loop.
Please read the Documentation for ArrayList in Java.
https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
There you actually can see, that ArrayList.remove(Object o), removes o if it is in the list, so your method is not needed.
So the answer is, find the book Object with your ID and then remove it. Or better use a Map to store your data.
In your case it would be
Book b = null;
for(Book book : books) {
if(book.getBookId().equals(bookId)) {
b = book.getBookId();
break;
}
}
books.remove(b);
Or if you are into Java8 which you really should be :D
books.stream().filter(b -> b.getBookId().equals(bookId)).getFirst().ifPresent(books::remove);
You need to use iterator, otherwise you will get java.util.ConcurrentModificationException
public static void delete(String bookID) {
for (Iterator<Book> it = catalog.listIterator(); it.hasNext(); ) {
Book book = it.next();
if (book.getBookID().equalsIgnoreCase(bookID)) {
it.remove(book);
return;
}
}
}
Note: equalsIgnoreCase is used to discard case differences.
java.util.ConcurrentModificationException is thrown, because you are doing 2 operations on the list: iteration and removal. So, actually, there is another approach - copy the list on each step of iteration.
public static void delete(String bookID) {
for (Book book : new ArrayList<>(catalog)) {
if (book.getBookID().equalsIgnoreCase(bookID)) {
catalog.remove(book);
return;
}
}
}
Note: Because of performance considerations (quadratic memory usage and linear removal on each step), I don't recommend the last approach. I give this example only to stress out the underlying reason why java.util.ConcurrentModificationException is thrown.
Removal of elements, while an iterator is being used, is undefined.The better approach would be to use removeIf.
catalog.removeIf(eachElement -> eachElement.getBookID().equals(bookId));
You need to use iterator in order to delete item while using loop .
also double check if the id exist (make some System.out.println("test") and check if it is entering the scope).

Should I avoid returning null in my java function? [closed]

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
I don't find the appropriate solution for my question. As far as I know returning null is a not a good way to write clean code, as the book Clean Code says. However there are many different opinions about this practice, and I am not sure about which one fits on my function.
private EArea getSimilarExistingArea(EImportArea importedArea) {
for (EArea existingArea : exsitingAreas) {
EList<EPoint> importedAreaPoints = importedArea.getPoly().getPoints();
EList<EPoint> existingAreaPoints = existingArea.getPoly().getPoints();
for (EPoint importedAreaPoint : importedAreaPoints) {
for (EPoint existingAreaPoint : existingAreaPoints) {
if (importedAreaPoint.equals(existingAreaPoint))
return existingArea;
}
}
}
return null;
}
What should I return if there is not an existing similar area?
PD: For optimize my code I am breaking the loops with the return if an existing area is founded.
You should take a look at the Optional class!
Make your method return type Optional<EArea> and simply return Optional.ofNullable(existingArea) you will have to slightly modify your Code but the benefits of Optional are really worth it!
Finally I used Optional Class to solve my problem.
Here is the code:
private Optional<EArea> getSimilarExistingArea(EImportArea importedArea) {
for (EArea existingArea : baseLineService.getBaseLine().getAreas()) {
EList<EPoint> importedAreaPoints = importedArea.getPoly().getPoints();
EList<EPoint> existingAreaPoints = existingArea.getPoly().getPoints();
for (EPoint importedAreaPoint : importedAreaPoints) {
for (EPoint existingAreaPoint : existingAreaPoints) {
if (importedAreaPoint.equals(existingAreaPoint))
return Optional.of(existingArea);
}
}
}
return Optional.empty();
}
And here is how I check the returned value:
if (getSimilarExistingArea(importedArea).isPresent())

Categories

Resources