ForEach and Facelets - java

My managed bean :
public List<String> getLiQuickNav(){
System.out.println("I'm here...");
List<String> l = new ArrayList<String>();
l.add("toto");
l.add("tata");
l.add("titi");
return l;
}
My forEach :
<c:forEach var="categorie" items="#{mainControleur.liQuickNav}">
<h:outputLabel value="${categorie}"/>
</c:forEach>
My output stream :
I'm here...
I'm here...
I'm here...
I'm here...
As you can see "getLiQuickNav( )" is call 4times by my ForEach. But I just wan't to call "getLiQuickNav( )" one time...
How to call it just one time ?
Bonus question:
Why "getLiQuickNav( )" is call 4time whereas I have only 3item "tata,titi,toto" ?
Thank's

You can't control the number of times that getLiQuickNav() is called - consider caching your list so it isn't rebuilt between calls.
private List<String> l;
public List<String> getLiQuickNav()
{
if ( l == null )
{
System.out.println("I'm here...");
l = new ArrayList<String>();
l.add("toto");
l.add("tata");
l.add("titi");
}
return l;
}
As well you should be using <ui:repeat/> rather than <c:forEach/>. See this blog entry for why.

Answer
You're reinitializing the state in a getter every time. That is meant to be an accessor, not a way to initialize state. Don't create the list in getLiQuickNav, create in a constructor or setter.
Bonus
The first time you call getLiQuickNav() you initialize the list, the reference to this list gets returned and stored in a scope to evaluate your expression (.liQuickNav) and then the getLiQuickNav() is called by convention 3 more times for each item in the list.
It should get called once if you return the same list every time. You're returning a new one every time.

Getter's in Java (in any context, to include for Faces Managed Beans) should not generate anything - they should just return a value. Create the list before hand and return it.

Related

Converting Optional<> to List<>

I have a section of code that used to utilize Optional<Department>, but due to some errors I worked out I am now converting it to List<Department>. Obviously this means I now have to change the return types and other method calls. Here are my questions:
I changed my returns to "new LinkedList<>()" (indicated in the code below) but is that correct?
There is a red error under ".isPresent" (indicated in the code below) with error message "The method isPresent() is undefined for the type List<Department>". What should I be changing that to?
Below is the updated code with comments indicating where errors are now occurring. Any help and explanations would be GREATLY appreciated!
public List<Department> delete(String department_ID) {
if ((department_ID == null) || (department_ID.isEmpty())) {
return new LinkedList<>(); //<<<<<<<<<<<<<<< used to be "return Optional.empty();"
}
List<Department> existing = get(department_ID);
if (existing.isPresent()) { //<<<<<<<<<<< red error under ".isPresent()"
String sql = "DELETE employee.*, department.* " + "FROM employee, department "
+ "WHERE employee.department_ID = :department_ID AND department.department_ID = :department_ID;";
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("department_ID", department_ID);
int rows = jdbcTemplate.update(sql, parameters);
if (rows > 0) {
return existing;
}
}
return new LinkedList<>(); //<<<<<<<<<<<<<<< used to be "return Optional.empty();"
}
I changed my returns to "new LinkedList<>()" (indicated in the code below) but is that correct?
I have googled the error message for my ".isPresent" error and cant find any explanations that fit
tl;dr
Change:
if (existing.isPresent()) { …
… to:
if ( ! list.isEmpty() ) { …
Details
You said:
red error under ".isPresent" (indicated in the code below) with error message "The method isPresent() is undefined for the type List".
The variable existing holds a reference to a List object. If you look at the Javadoc for List, you find no method named isPresent. So of course trying to call a non-existent method generates an error from the compiler.
That isPresent method was from the Optional class. The method checks to see if the optional holds a payload or if the optional is empty.
You seem to be switching to a style where you always expect a List, even if the list is empty (no elements).
If you want to be defensive, you can check that the list object exists.
if ( Objects.nonNull( existing ) ) { … }
But you can omit that null check if you are confident that such a condition cannot exist.
You may want to check if the list is empty, to avoid a needless call to your database. If so, change that code to:
if ( ! list.isEmpty() ) // Perform database work only if list has some elements.
You have other issues. Among them:
Generally the convention in Java is to avoid underscores in names. And generally best to avoid ALL-CAPS. So departmentId, not department_ID.
When returning lists, generally best to return an unmodifiable list. If the calling programmer needs a modifiable list, they can easily make from the returned unmodifiable list.
To get an unmodifiable list, use List.of rather than new LinkedList<>().
I cannot understand why your delete method would return a list. You may believe that you are reporting rows that got deleted, but technically you are not.
By the way, a tip: Text blocks can help with embedded SQL.
Instead of returning new LinkedList<>() you could return List.emptyList().
isPresent() is a method of Optional, but you assign the outcome of method get(department_ID) to an instance of List. You can check the List using
if(!(existing == null || existing.isEmpty())) {

Java List being modified from somewhere despite being of Collections.unmodifiableList()

I have three lists in my program.
ONE A global list of all items. ALL
TWO A list showing all items that are available to the user. VISIBLE
THREE A list of all items currently visible on the screen. SHOWING
The lists were declared as so:
ONE = external source
TWO = ONE
THREE = ONE
I have this issue when responding to the user filtering specific items. The function will iterate over THREE and List.remove(index) items that match the filtered item. The function does not interact with TWO. Despite this TWO is modified to be equivalent to THREE despite the initial declarations not being run again (I checked with the debugger and can't work out when TWO is ever modified).
I tried changing TWO to be a Collections.unmodifiableList() but it was still modified?
I fixed the issue with some serious jankiness.
Object[] temp = new Object[ONE.size()];
temp=ONE.toArray(temp);
TWO = Arrays.asList(temp);
Awful I know... It works because Arrays.asList is immutable but surely the unmodifiable list is also immutable?
Added Code for those requesting.
Initialisation Code:
protected void onPostExecute(List<SpaceObject> visibleObjects){
hideLoading();
SpaceObject[] atom = new SpaceObject[visibleObjects.size()];
atom=visibleObjects.toArray(atom);
VISIBLE_OBJECTS = Arrays.asList(atom);
SHOWING_OBJECTS = visibleObjects;
addToView(visibleObjects);
}
Responding to removing or adding items.
private void showSpecificItems(String itemType, Boolean remove){
int i = 0;
if (remove) {
while (i < SHOWING_OBJECTS.size()){
if(SHOWING_OBJECTS.get(i).getType().toLowerCase().matches(itemType.toLowerCase())){
SHOWING_OBJECTS.remove(i);
}else{
i++;
}
}
}else{
System.out.println("remove");
while(i < VISIBLE_OBJECTS.size()){
if(VISIBLE_OBJECTS.get(i).getType().toLowerCase().matches(itemType.toLowerCase())){
SHOWING_OBJECTS.add(VISIBLE_OBJECTS.get(i));
}
i++;
}
SHOWING_OBJECTS = sortBrightest(SHOWING_OBJECTS);
}
addToView(SHOWING_OBJECTS);
}
If you have code like this
List<Object> ONE = someMagic();
List<Object> TWO = ONE;
List<Object> THREE = ONE;
Then you have three things all pointing at the same list.
If you want them to be different, you could try something like this:
List<Object> ONE = someMagic();
List<Object> TWO = ONE.clone();
List<Object> THREE = ONE.clone();
This way they make actual different lists.
protected void onPostExecute(List<SpaceObject> visibleObjects){
hideLoading();
// this line is useless - you allocate an array only to immediately toss it away?!
SpaceObject[] atom = new SpaceObject[visibleObjects.size()];
atom=visibleObjects.toArray(atom);
// this uses atom as its backing array, which comes from visibleObjects
VISIBLE_OBJECTS = Arrays.asList(atom);
// this obviously atom as a backing array
SHOWING_OBJECTS = visibleObjects;
addToView(visibleObjects);
}
So to fix this, you need to remove the dependency on that backing array
protected void onPostExecute(List<SpaceObject> visibleObjects){
hideLoading();
VISIBLE_OBJECTS = visibleObjects.clone();
SHOWING_OBJECTS = visibleObjects.clone();
addToView(visibleObjects); // probably bad form, but I doubt this will keep a reference, so it's "acceptable"
}
if clone is not available for you, you can do it a little more complicated
protected void onPostExecute(List<SpaceObject> visibleObjects){
hideLoading();
VISIBLE_OBJECTS = new ArrayList(visibleObjects);
SHOWING_OBJECTS = new ArrayList(visibleObjects);
addToView(visibleObjects); // probably bad form, but I doubt this will keep a reference, so it's "acceptable"
}
I tried changing TWO to be a Collections.unmodifiableList() but it was still modified?
The javadocs say this about unmodifiable views as created by that method:
An unmodifiable view collection is a collection that is unmodifiable and that is also a view onto a backing collection. Its mutator methods throw UnsupportedOperationException, as described above, while reading and querying methods are delegated to the backing collection. The effect is to provide read-only access to the backing collection. ...
Note that changes to the backing collection might still be possible, and if they occur, they are visible through the unmodifiable view. Thus, an unmodifiable view collection is not necessarily immutable.
In short, unmodifiableList() does not have the properties that you expect. If you want an immutable snapshot of a mutable list, you need to copy it.

How do I access the first non null term of a List in Java?

So I have a method (of which I can't change the parameters, or else this could have been made easier through HashMaps...more on this later), that passes an item as a parameter. Now I have a list of instances from this other class, of which one of its attributes is of the same type of this item, and I want to find the instances in the list which correspond to this item (of which there should be only one). This is what I did to find this:
List<Instance> instances = ...
public static void checkItems(Item i) {
List<Instance> n = new ArrayList<>();
instances.forEach(p -> n.add(p.i == i ? p : null));
Instance currentInstance = n.get(0);
//Instance currentInstance = instances.stream().filter(p -> p.i == i).collect(Collectors.toList()).get(0);
}
You'll probably notice two things straight up:
I used a conditional operator which adds a null value to the list when the condition isn't passed
My commented code which was another attempt to solve this issue
So in the first case, I put null because it requires you to put something, and a null value is probably easier to work with, which is why the question arises: How do I access the first non-null value in a list (without resorting to iterating over the entire list to find it...)?
You may notice that I just assign the first value of the list with n.get(0) to currentInstance, because I know that only one value will have passed the test. However, due to some other code that I apply to currentInstance, this value cannot be null.
Just a note on the second point: the way I tried to solve it with streams actually works exactly as planned, except that for some reason the list of instances recovered is not a direct copy of the original instances. This resulted in the values of some of the attributed to have been reset to default values, therefore rendering this method useless.
EDIT: I just wanted to mention that the streams method wasn't working because of some silly mistake that I made in another class, there was nothing wrong with the code so I'll be using that bit to solve my problem :D
If you know that only one p passes the test, I don't know what the point of creating a list with a load of null values plus p is.
Your problem seems to stem from wanting to use forEach. In my opinion, you should almost always use a for loop in preference to forEach. With a simple for loop you can just use break when the item is found.
In detail:
Instance p = null;
for (Instance q : instances) {
if (q.i == i) {
p = q;
break;
}
}
if (p == null)
throw new IllegalStateException(); // It wasn't there.
// Do something with p.
You could do it this way:
Instance currentInstance = instances.stream()
.filter(p -> p.i == i)
.findFirst()
.get(); // you can use get if you are sure there's one instance
The predicate p -> p.i == i seems suspicious. Why not using equals() instead?
As described, this would normally be solved with streams in the following way:
Optional<Instance> first =
instances.stream().filter(p -> p.i == i).findFirst();
(of which there should be only one)
Of which there definitely is only one, or of which there might be more than one. (And if there's more than one, then what? Is that an error?) It sounds like it might be that you should have a Set<Instance>, not a List<Instance>. Just an observation.
You can do it like
instances.forEach(p -> {
if (p.i == i) n.add(p);
});

Array is re-initialized every time

Hi i am trying to add the values to list as show in below code. i am getting error.
if i use like below
for (String n2 : number ) {
List<String> ARRAY = new ArrayList<String>();
if (!ARRAY.contains(n2)) {
Email(n2);
ARRAY.add(n2);
}
}
if i am using above. Though already email sent with value n2 again it is sending again. For first it has to sent but for second time n2 should be in array but still it sending. any one help. if n2 is passed to email second time it should not pass.
I am re-posting question as pervious one seems not clear i guess.
You need to move the ARRAY outside of the for loop
List<String> ARRAY = new ArrayList<String>(); // maybe as a class field
for (String n2 : number ) {
if (!ARRAY.contains(n2)) {
Email(n2);
ARRAY.add(n2);
}
}
List<String> ARRAY = new ArrayList<String>();
This line needs to be outside of your loop.
Why?
Simple. It's an issue of scope. Scope is the the lifetime and accessibility of a variable. In this case, you declare it inside of a loop, so the scope of that variable is, you guessed it, the loop. When the loop exits, the variable is destroyed.
You need to move it outside, so that the variable persists for the lifetime of the loop.
Extra Reading
Please, read the Java Naming Conventions.

Should enhanced for loops include a function returning a list

I was just concerned about enhanced for loops calling a method directly.
Nested inside the code is my question in capital letters:
public class ExtendedForLoop {
public static List<Integer> returnList() {
System.out.println("Hurray ----> ");
List<Integer> abc = new ArrayList<Integer>();
abc.add(5);
abc.add(10);
abc.add(20);
return abc;
}
public static void main(String args[]) {
for (Integer i : returnList()) { // <----- OPTION 1. Include function call in extended loop.
System.out.println(i);
}
List<Integer> list = returnList()
for (Integer i : list) { // <----- OPTION 2. Provide list to function call.
System.out.println(i);
}
}
}
I prefer option 2, as some exception can be dealt with.
However if no exceptions are expected then option 1 can reduce unnecessary declaration of a new variable, hence reducing clutter.
But,
In general.
Which option is preferred ?
If it is option2 and the only reason for chosing option2 is handling exceptions, then should we use option1 if no exceptions are expected ?
I prefer using option 1 if I'm the owner of the code that returns the list and can guarantee that null will never be returned.
If I'm not the owner, I prefer to use a different construct though
for(Integer i : guaranteeCollection(resultList())
{
// dostuff
}
public static &ltT> Collection&ltT> guaranteeCollection(Collection&ltT> c)
{
return c != null ? c : Collections.EMPTY_LIST;
}
This avoids creating unnecessary variable declarations in your code and prevent NPEs.
I think second approach with null check is safer.
enhanced for loop will through NullPointerException if method returns null.
It depends on your system design:
Many project targets avoiding null objects.
If you are sure that returnList() will never return null (It should return an empty list instead (or Collections.emptyList), then go for solution 1, other wise for 2.
Well if you are dealing with NullpointerException in case then i prefer going with Option 1 as we are making an extra variable "list" on the stack which will occupy some memory also will reduce the performance by some bit.

Categories