Multiple lists or list and getSublist() (Java) - java

I have an abstract class 'entity' and Objects (that extend 'entity') that implement different interfaces.
I also have an ArrayList that contain all those different Objects.
Now if I need access to all entities that implement a certain interface (to use its methods), I use the following method (which returns a filtered list of 'entities' that implement interface 'IDirectFire'):
public ArrayList<IDirectFire> getDirectFireSublist() {//direct fire sublist
ArrayList<IDirectFire> sublist = new ArrayList();
entities.stream().filter((it) -> (it instanceof IDirectFire)).forEach((it) -> {
sublist.add((IDirectFire) it);
});
return sublist;
}
Now to my question:
Should I further work with this method or should I create a new ArrayList that exists besides 'entities' and that I would need to manually update every time 'entities' changes?
I need to update 'entities' a lot so I'm not sure if it's more efficient to store multiple sublists and update them all every time 'entities' changes or if I should keep using methods to filter 'entities' and apply methods to those sublists. Keep in mind that those sublists would also be used in a loop in other methods e.g.:
private void resetFirestatusIDF() {//reset firestatus (IDirectFire)
getDirectFireSublist().stream().forEach((it) -> {
it.dfHasFired(false);
});}
Is this viable?
Thanks in advance!

Now to my question: Should I further work with this method or should I create a new ArrayList that exists besides 'entities' and that I would need to manually update every time 'entities' changes?
For which reason do you want duplicate the 'entites' data ?
1) You can put them only in a dedicated list. In this case, you don't need getDirectFireSublist() anylonger.
2) You can share them between the two lists without duplicating them.
In this case, you must update the added and the removed entity element because only the modified elements will be updated. But it is rather straight to implement.

If all you need is to loop over a subset of your items, creating a new list is wasteful. Just return the filtered Stream.
public Stream<IDirectFire> getDirectFire() {
return entities.stream().filter((it) -> (it instanceof IDirectFire));
}
You could also use Guava and return a filtered Iterable instead:
public Iterable<IDirectFire> getDirectFire() {
return FluentIterable.from(entities).filter(IDirectFire.class);
}
Then, to loop over the items elswhere:
private void resetFirestatusIDF() {
getDirectFire().forEach((it) -> it.dfHasFired(false));
}

It is better to filter them. It will create a more clear and understandable code at a price of negligible performance decrease which unless you are filtering milliards of elements should be negligible.
The second thing I have noticed is you stream usage for code fragment 1. I would recommend you and alternative approach to it :
> public ArrayList<IDirectFire> getDirectFireSublist() {
> return entities.stream().filter((it) -> (it instanceof IDirectFire)).collect(Collectors.toList());
> }

wakjah mentions in a comment that instanceof is a bit of a design smell. With that in mind, one alternative solution would be to use a Visitor pattern.
public abstract class Entity {
public abstract void acceptVisitor(EntityVisitor visitor);
...
}
public interface IDirectFire {
default acceptVisitor(EntityVisitor visitor) {
visitor.visit(this);
}
...
}
public class ResetFireStatusVisitor implements EntityVisitor {
public void visit(IDirectFire directFireEntity) {
directFireEntity.dfHasFired(false);
}
}
Then, to loop over the items:
entities.forEach(entity -> entity.acceptVisitor(new ResetFireStatusVisitor()));
The ResetFireStatusVisitor calls dfHasFired(false) on anything that implements IDirectFire. In EntityVisitor you can specify default no-op implementations for the other subtypes of Entity.
I'm not suggesting you do this for simple cases, but for large-scale designs this might be a useful answer to this problem. On the other hand, it might not -- this pattern has its share of design smells too.

Related

How can I process all readed items in groups instead one to one?

I want validate the start and end date of my records that share a producid in a table. I will read all registers in database with JDBCItemReader ordering by productId.
This is a example of my table:
ID|Name|StartDate|EndDate|ProductID|.....
In normal chunk processing, I will read - process items one-to-one and then write them but I want recover a list in My processor while ProductId doesn't change and when this Id change, make some validations and updates to my items and then pass them to writers but I think that this It's not possible because I can't send a list of items to my writers, I have to send them one to one.
Example that I need to do (Pseudo-described):
#Component
public class CheckAuxDuplicatesProcessor implements ItemProcessor<MyDTO, MyDTO>{
private BigDecimal currentProdIdProduct = BigDecimal.ZERO;
private List<MyDTO> currentList;
#Override
public MyDTO process(MyDTO arg0) throws Exception {
if(!currentProdIdProduct.equals(dto.getProdIdProduct())){
//call to process items (Not implemented yet)
//return list of items
currentList.clear();
}
currentList.add(dto);
return null;
}
}
Maybe it's possible if I create a full Tasklet class and implement all the logic in the execute method (read all registers), loop them and make the validations, edit them and finally pass them to the readers.
Anyway I think that this last option is a bad-design idea. But I don't know other way to make some like this.
Take a look at the AggregateItemReader for inspiration. You can use it to create aggregate items (List of items) as groups.
In your case, when the ID changes while reading items, you can consider that your are starting a new group.

Java collection : criteria based traversing or another view to a collection

Is there any way or if any java library available which can let me traverse through selected list items only(not all) which satisfies the condition?
For example: I have a list of employee, and I want to traverse the list of employees who are manager only. I don't want to put a condition or filter but want to traverse the list of manager only.
For this, I can define the criteria while creating the list. So every time, when I'll add an item to the list a pointer to a list item, which satisfies the criteria, will be saved in another list.
It's like providing another view to original list.
Although it can be done using filter, but I would have to basically access each list item, compare and then process.
It can have memory overhead as it'll maintain extra list for each criteria, but I believe it'll reduce processing time.
I am expecting that my list would not contain more than 30 items on average.
Update
After some brainstorming, I have come up with below solution.
View<T>
List<T>
boolean checkCondition(T);
boolean updateView(T);
managerView
boolean checkCondition(T){
return token.getDesignation == designation.MANAGER;
}
salaryView
boolean checkCondition(T){
:
}
ViewableList<T> list
list.addView(managerView)
list.addView(salaryView)
ViewableList<T>
List<View<T>> views;
add(T){
originalList.add(T);
foreach views{
if(view.checkCondition(T)){
view.add(T);
}
}
}
addView(View){
views.add(view)
}
I can achieve Insert, Search, and Delete operation easily. But I am still finding difficulty to update the view when the field of view of an object is updated.
Possible solutions
I annotate list item's field; Write an aspect. So whenever the value of annotated field is changed, it can call updateView() of corresponding view.
Employee{
#View(type=DesignationView.class)
Designation designation;
}
But there is a chance that a field is used in constructing multiple views. So I would have to pass list of view classes in #View annotation, which looks pretty odd. Moreover, I want to avoid use of reflection and aspect due to performance. Otherwise there'll not be any sense to put all this effort.
Please lemme know if you have an idea how I can implement it.
Wouldn't it be better if you use Map. In this map, key could be category and value will be list. So when traversing only get the entry for that key.
And how do you expect such a thing to be coded in such a way as to be so generic that it's useful as a general purpose library rather than specific to your very narrow requirements?
Which would be the only kind of implementation that it is a sensible idea to release as a standalone library of course.
So no, something like that isn't going to exist. You're going to have to create some of your own code.

Iterate list inside list inside list java

I got a question. Is there a simple solution to iterate over the list that is inside of a list and inside of a list again?
So my point is I have few of lists inside of each other (based on xml unmarshall) and I sometimes do not know how deep is the structure.
Exsample:
class Car{
private List<Door>
}
class Door{
private List<Parts>
}
class Parts{
private List<Some1>
}
}
class Some1{
private List<Some2>
}
So how can iterate from Car to Some2 without knowing if there is a list or is empty in a "good way"? I mean without 5-times nested "for" loops mixed up with another 6 "if's".
DeeV makes a good suggestion about each class iterating over their respective lists.
As a client using the Car class, you may want to get all the Some2s that it contains. If you do this:
car.getDoors().getParts().get...
you expose the internals of the Car class. A much cleaner solution would be to have the following method in the Car class:
public List<Some2> getSome2s()
This way, if the internals of Car change (perhaps using a different Collection type) your client code will not break as long as a list of Some2s is still returned.
There is no easier way than nested for loops. If you want more speed try using different structures like Maps.
First implement composite pattern with your classes after you'll be able to recursive to leafs and aggregate them in a list.

Use objects in Enum (Specifically Place in GWT)

I got an application in GWT that will consist of a listbox with more than 50 items. When selecting one I'll go to the corresponding place.
To avoid hard coded values and to share with the server part, I created an Enum lets call it TableEnum
So Table Enum is composed of a key and a displayName.
Which I then use to fill my combo. Once the selection is done, I got the value and so need to get the Place to go to.
That's why I created a factory that take the value of the selection and return a Place object.
First solution I was about to do is transform my value in TableEnum object et do a switch/case creating the correct associated Place.
But I was also thinking about adding the Place directly as a field of my Enum. This would avoid the switch/case and I would only need to do tableEnum.getPlace().
But I'm not really confident that this can be called a good practice. In my head Enum were simple objects not really knowing what was around them.
Thanks for information
Enums in Java are not just a placeholder for integers, or just some constants (such as some languages). Enums are classes with fixed number of objects, so it is a good practice to give your enums more brain, and always forget about lots of if/else or *switch/case*es.
If each item in the enum is associated to only one place, you can create an abstract method on your enum to get the place.
public enum TableEnum {
FIRST(){
public Place getPlace(){ return new FirstPlace(); }
},
SECOND(){
public Place getPlace(){ return new SecondPlace(); }
};
public abstract Place getPlace();
}
Later, you can access the place like so:
TableEnum t = ...
t.getPlace()
like Danny Kirchmeier's, but maybe less code:
enum Table {
first(Place.place1), second(Place.place2);
Table(Place place) {
this.place = place;
}
final Place place;
}
maybe your place should be an enum?

How do I sort the List by a property of the Objects in the collection?

So I've resigned myself to not being able to use the order of a List reliably because hibernate reverses it and everyone says don't do it, so I've added a field to my class as position. I have:
#Entity
class Procedure {
...
int procedureId;
List<Task> tasks;
...
}
#Entity
class Task {
...
int taskId;
int position;
}
Now I don't know how to approach interacting with the list. Should I just sort it by position when I first get it from the db and start working with it, and then I can leave all the user-rearranging code that I've already written and then just reset all the positions on save to the order the list so I can resort when I get back?
SKIP TO ACTUAL QUESTION HERE:
This seems to be the best approach, but HOW do I sort the List by a property of the Objects in the collection?
To sort by position, for example, you can use
java.util.Collections.sort(tasks, new Comparator<Task>() {
#Override
public int compare(Task t1, Task t2) {
return t1.getPosition() - t2.getPosition();
});
Yuval =8-)
If you want the list order to be preserved by Hibernate, you should probably use <list-index> to map the index column, as described in 6.2.3 Indexed Collections, instead of adding it as field of Task and sorting it yourself.
This way, your Java code doesn't have to worry about the index values at all. The list will be properly sorted when returned by Hibernate, and Hibernate will take care of updating the indexes when the list is modified.

Categories

Resources