Iterate list inside list inside list java - 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.

Related

use Lombok #Builder #Default #Singular to initialise List<>

Disclaimer: I am kind of new to Java :)
I am running a bunch of selections on some data and in order to keep track of what happens at each stage of the the selection I use int counters. These counters are all in a data object:
public class MyCounters {
private int counter0;
private int counter1;
...
}
I also have to count how many candidates end up in a given number of categories, which I account for with an enum. To do this I created List<Integer> where the index of the list covers the values of the enum.
private List<Integer> myList;
And later in the code I need a dedicated method to initialise the list with zeros:
for (MyEnum i : MyEnum.values()) {
myList.add(0);
}
In the main code then, once the final category has been assigned, this happens:
myCounters.getMyList().set(myEnum.ordinal(), myCounters.getList().get(myEnum.ordinal()) + 1);
I was suggested that the declaration/initialisation steps can be improved using Lombok's #Builder.Default functionality (or maybe #Singular), but I can't really find out how: in the end I need to initialise a List<Integer> to as many zeros as the values in the enum.
Is it really possible to do this using Lombok's extensions? Or are they targeted for something different?
Lombok's #Builder + #Singular on their own will initialize your List with an empty ArrayList, and that's it (they won't initialize this List with any elements, like zeroes). #Builder.Default could do that (you don't need #Singular then), but I would not follow that path if possible.
I don't fully understand what you want to do, e.g. I don't know if you have only one enum (MyEnum), or if there's more than one enum.
If you have only MyEnum, you'd be much better off using a different data structure than List:
An EnumMap is the easy choice, because it's native to Java:
initialization: EnumMap<MyEnum, Integer> myMap = new EnumMap<>(MyEnum.class)
incrementing: myMap.merge(myEnum, 1, Integer::sum)
final result: myMap.getOrDefault(myEnum, 0)
The best data structure for this, though, would be a multiset. One external library that supports mulitsets is Guava with its Multiset:
initialization: Multiset<MyEnum> myMultiset= HashMultiset.create()
incrementing: myMultiset.add(myEnum)
final result: myMultiset.count(myEnum)
Sticking to your architecture, I guess you have to initialize the List within a class that uses Lombok. That can be achieved as follows:
#Builder
public class Foo {
#Builder.Default
private List<Integer> myList = Arrays.asList(0, 0, 0);
}
Arrays.asList is how you can initialize a List with default values using the standard Java libraries. I know it can be a bit confusing to use a class called Arrays instead of List or Collection, but you can find more information on its Javadoc (here the doc for Java 8). The result of that initialization is a list with three Integers set to 0. You just need to put as many as you need.
The reason to use the annotation #Builder.Default on the myList field is to make the builder constructor aware of the default initialization that otherwise would be skipped by the Lombok's builder.
For brevity, I only included the very specific code for initializing your List and the builder. Note that probably you'd want to use also the Lombok annotations #Data and #AllArgsConstructor in combination with it.
You can find more information on the Lombok official documentation
Honestly, I suggest a different architecture:
Consider not using Enum.ordinal(). It will work fine if you just care about "one" point in time, but if you persist your data somehow then things break apart as soon as you want to compare different persisted data (and the enum changed in the meantime)
Maybe consider LongAdder.
Meaning: use a Map<YourEnumType, LongAdder> to count things. Retrieve the counter, call its add() method, done.

Multiple lists or list and getSublist() (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.

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.

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?

Decoupling - OOP

I have a simple question (working with Java). I have two classes, one represents a Document, a second represents a Word.
The Document class needs to know some info about the words that is kept in Word. My question is, what's the best way to decouple the two classes? I have 2 options in mind:
Have no connection between the classes, and each time I call a method in Document, I pass it an object of Word (so I have a third class with a main method that initiates
both Document and Word).
Declare a private object of Word inside Document.
One thing to note, I only have one object for Word and one for Document. I don't create a new object for every new document or word. I store a list of the entire documents in Document, and a list pf the entire words in Word.
Thanks!
I don't agree with your understanding of Decoupling. Decoupling is not just about which objects create other objects, it's also about which objects know about the behaviour of other objects and (crucially) what needs to change in (your example) Document if Word changes.
However, also I really don't understand what your mean by these two phrases:
I only have one object for Word and
one for Document. I don't create a new
object for every new document or word.
I store a list of the entire documents
in Document, and a list pf the entire
words in Word
Start from Document. What can objects of this class do? You seem to be saying that
class Document {
private List<??OfWhat??> allDocuments;
}
If class Document contains a List, what's it a List of? I think you need:
class Shelf {
private List<Document> allDocuments;
}
class Document{
private List<Word> wordInOneDocument;
}
class Word {
private String wordContents;
}
Now a Shelf could offer methods such as getRecentDocumets() findDocumentsContaining(String text)
and Document could contain getWordCount() and insertParagraph(List, START); and so on.
To have a better discussion we need to see a bit more of what you had in mind, a bit more about behaviour.
I do agree with your general thought that there is Something other than Document and Word out there. Something that can reasonably invoke methods such as createDocument() and insertParagraph()
From my point of view...
public class Document{
private List<Word> words = new ArrayList<Word>();
public void setWord(ArrayList<Word> words){this.words = words;}
public ArrayList<Word> getWord(return this.words;)
}
It's a reasonable approach. In this example you can create a Document without any Word's, which makes for an empty Document, which is valid.
You could still create a third class as you suggest, however, I don't see the benefit with it.
Your problem should be solved by composition. Thus having a List of Word seems to be a valid approach. By separating out Documents and Words, you have already achieved the required de-coupling. I do not get your exact point of de-coupling Document and Word objects.
Your question is
what's the best way to decouple the two classes? I have 2 options in mind:
Neither option satisfies your request. If they are going to work together, then they are going to be coupled. The only thing is how tight or loose the coupling is.
Both of your options sound like tight coupling. A form of looser coupling would be to store an interface reference and take it in on a constructor or setter method.
If you want to decouple the classes, one standard way is to use an interface:
public interface IWord {
...
}
public class Word implements IWord {
...
}
public class Document {
public boolean append(IWord word) { ... }
...
}
This way both Class and Word depend on IWord, but neither class nor Word depends on the other. This is known as Dependency Inversion.
Well first of all I think you're naming your classes incorrectly.
I don't create a new object for every new document or word. I store a list of the entire documents in Document, and a list pf the entire words in Word.
Judging by what you said here you have something like this:
public class Words {
private List<Word> = new ArrayList<Word>;
// getters+setters
}
public class Documents {
private List<Document> = new ArrayList<Document>;
// getters+setters
}
And you want to use the Words class in the Documents. If you want to do that, that means you can't decouple it (as it's against the very definition of the word "decouple"). I'm guessing here again, but I think you want to code it so you can change the implementation of the Documents class so in the future it could use another class like for example BetterWords.
In order to do that I would create either an abstract class or an interface (depending on the rest of your architecture) and then make the Words class either extend it or implement. Then you can do something like this:
public class Documents {
private List<Document> = new ArrayList<Document>;
private IWords wordsInterface = new Words(); //in case you want to make an interface
private AbstractWords wordsAbstract = new Words(); //in case you want to make an abstract class
// getters+setters
}
Or you can put it in the Document class (the words), don't really know where you want them.

Categories

Resources