This may be a duplicate, but I don't know the correct terminology to even search for what I want, so I apologise if this is and the title is not completely specific.
This is my scenario:
I have 2 different types of Objects I want to map to each other, call them ObjectA and ObjectB. These Objects are generated in a for-loop. I want each instance in an iteration to be mapped to the other. So basically, ObjectA(1) - ObjectB(1), ObjectA(2) - ObjectB(2), etc.. And there will be roughly 500 - 3000 entries to map.
The reason for this is some methods will be passed ObjectA and I need to get the corresponding ObjectB, and vice versa. I also can not use the initial loop index as reference, it just needs to be one of the objects.
I have tried making use of Guava HashBiMap, which works, but I don't like it for several reasons. 1) This is the only instance I will be making use of any Guava class, and I don't necessarily want to add ~500kb to my package for it. (This is for a mobile app, so trying to keep it small) and 2) I need to iterate the objects every frame, and iterating through the keySet() was giving significant memory allocation. I am sure there are ways around this and it was probably just some mistake I made, but still.. reason 1.
The current solution I have since I know the indexes are mapped, is to just have 2 ArrayList's, (or actually libgdx Array's, but for the purpose of understanding logic we can assume ArrayList), and I simply do;
ObjectA objectA = objectAList.get(objectBList.indexOf(objectB));
And vice versa.
Anyway, I don't like this solution either, it feels expensive and I sure there is a much simpler and faster method, I just don't specifically know what to search for.
Thanks for the help!
Maybe this will be helpful for you. There is an interface in Apache Commons Collections called BidiMap
https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/BidiMap.html
Classes implementing this interface have methods u are looking for. I mean getting key by value and vice versa and this package weighs about 150 kb.
regards
Related
I have an ArrayList where I want to call two methods on the first two objects in the list, and different methods on the rest, how can I do this the easiest way?
So far I have this
ArrayList<Material> materials = new ArrayList();
StyklisteMetodeKlasse.fillArray(materials);
for(Material materialer: materials.subList(0, 1)){
int brugerInput = 0; // this is only a temporary varible
materialer.setAmount(Material.calculatePlanks(brugerInput, materialer.getLength()));
materialer.setAmount(Material.calculatePlanks(brugerInput, materialer.getLength()));
//here is some code where i call different methods on the rest of the materials
When I call a method on the "materialer" does it apply for all the objects or just the first, then the second?
The best approach would most likely be the simplest one. Using polymorphism, and try and get the type of the object at runtime and select what you need to do, would be a sleek solution, but as you said, it might get complicated, especially if you do not have control over the structure and nature of the objects being passed to you.
Alternatively, you could make your classes implement an interface which abstracts the operation that you would need to do. This would allow you to always call the same method, without having to worry about who is what.
As it has been pointed out in the comments, having hardcoded index values could potentially cause more trouble than it will ever solve, since it assumes that who ever is consuming your method has inside knowledge of it how specifically works, as opposed to what it should do.
Most likely, the best approach would be to change your method to take 2 lists, as opposed to 1. This approach is easier to understand and also gives you more control and has you make less assumptions, which is usually always a good thing.
While working on a program, I thought if it is possible to add elements of multiple types e.g. Integer, String, Long etc in a List, without making it to accept everything of Object type.
I want to restrict the list to accept elements of only these three types? Is this possible?
There are few solutions of it, which I dont want to do
1) We can create a Pojo having all these three types as elements and insert that pojo.
2) A base class implementing datatype specific wrapper classes. In this case, user will know this abstraction while creating objects of different classes.
Can this be done in a better and more generic way?
What you can do as an alternative, is implement your own type of collection. This could have 3 add-methods accepting the different kinds of types you want and the default add-method should throw an UnsupportedOperationException.
This however might not be the ideal solution, since it might introduce bugs if you don't have a full understanding of how the collection you are implementing/extending should work internally.
You have Number to use with, well, any kind of number.
But there is no relationship between String and Number.
So, List<Object> is your only choice there.
And keep in mind: when you really have to deal with different types of elements - maybe List isn't the correct abstraction to use?!
In other words: if you have values of different types that belong together, you should rather consider creating a specific class to wrap around those values.
A better solution would be to use Map<TypeOfData, List<Type>> rather than hacking List to achieve it.
Although there are probably some hacked together work-around that may help you do this, the simple answer to your question is "no, this can't be done". Part of programming is using the right tool for the right job. In this case, it's almost certain that a List is the wrong tool to help you do this job.
I'm currently moving from C++ to Java for work and am having difficulty without const and pointers to make sure intent is always clear. One of the largest problems I'm having is with returning a modified object of the same type.
Take for example a filter function. It's used to filter out values.
public List<int> filter(List<Integer> values) {
...
}
Here everything is Serializable so we could copy the whole list first then modify the contents and return it. Seems a little pointlessly inefficient though. Especially if that list is large. Also copying your inputs every time looks quite clumsy.
We could pass it in normally, modify it and make it clear that we are doing that from the name:
public void modifyInputListWithFilter(List<Integer> values) {
...
}
This is the cleanest approach I can think of - you can copy it before hand if you need to, otherwise just pass it in. However I would still rather not modify input parameters.
We could make the List a member variable of the class we are in and add the filter method to the current class. Chances are though that now our class is doing more than one thing.
We could consider moving the List to it's own class which filter is a function of. It seems a little excessive for one variable though, we'll quickly have more classes than we can keep a track of. Also if we only use this strategy and more than just filtering happens to the List class will unavoidably start doing more than one thing.
So what is the best way of writing this and why?
The short answer is that there is not a single best way. Different scenarios will call for different approaches. Different design patterns will call for different approaches.
You've suggested two approaches, and either one of them might be valid depending on the scenario.
I will say that there is nothing inherently wrong with modifying a List that you pass into a function: take a look at the Collections.sort() function, for example. There is also nothing wrong with returning a copy of the List instead.
The only "rule" here is a Liskov rule (not the Liskov rule): your function should do whatever its documentation says it will do. If you're going to modify the List, make sure your documentation says so. If you aren't, make sure it says that instead.
Suppose you have a java object, would it be possible to detect where exists circular references inside that java object?
I would like to hear if there is a library to deal with this problem.
Thanks in advance.
Beware, this is not trivial task, but you already know this, right? ;)
In Java there is implementation of IdentityHashMap that is designed to be uses in such cases.
Conceptually simple, but can be quite complex to implement.
First off, a lot depends on what type of objects you're dealing with. If only a small number of object classes, and you "own" the classes and can modify them to add "search yourself" code, then it becomes much easier:
Add an interface to each class and implement the "search yourself" method in each class. The method receives a list of objects, and returns a return code. The method compares its own address to each object on the list, returning true (ie, loop found) if one matches. Then (if no match) it adds its own address to the list and calls, in turn, the "search yourself" method of each object reference it contains. If any of these calls results in a true return code, that is returned, otherwise false is returned. (This is a "depth-first, recursive" search.)
If you don't "own" the classes then you must use reflections to implement essentially the above algorithm without modifying the classes.
There are other search algorithms that can be used -- "breadth-first", and various non-recursive versions of depth-first, but they all represent trade-offs of one sort or another of between heap storage, stack storage, and performance.
A bit of a lateral answer, but how about using net.sf.json.JSONObject.fromObject(...) which checks for circular references and throws an exception if any are found. Also, you can configure the library to handle circular references differently if necessary. You would have to write a getter for those class members that exist in the cyclical relationship, since that is what JSONObject uses to create the JSON.
It seems to be simple task to code. Use Java Reflection API to crawl the graph of java objects and collect visited objects. If you visit object that is already in the set that means that there has to be a circuit. To crawl use BFS or DFS algorithms.
You don't need any library. It's simple breadth-first search alghoritm and reflection API. Of course you can try to find a library implementing this alghoritm.
This question already has answers here:
What does it mean to "program to an interface"?
(33 answers)
Closed 6 years ago.
This is a real beginner question (I'm still learning the Java basics).
I can (sort of) understand why methods would return a List<String> rather than an ArrayList<String>, or why they would accept a List parameter rather than an ArrayList. If it makes no difference to the method (i.e., if no special methods from ArrayList are required), this would make the method more flexible, and easier to use for callers. The same thing goes for other collection types, like Set or Map.
What I don't understand: it appears to be common practice to create local variables like this:
List<String> list = new ArrayList<String>();
While this form is less frequent:
ArrayList<String> list = new ArrayList<String>();
What's the advantage here?
All I can see is a minor disadvantage: a separate "import" line for java.util.List has to be added. Technically, "import java.util.*" could be used, but I don't see that very often either, probably because the "import" lines are added automatically by some IDE.
When you read
List<String> list = new ArrayList<String>();
you get the idea that all you care about is being a List<String> and you put less emphasis on the actual implementation. Also, you restrict yourself to members declared by List<String> and not the particular implementation. You don't care if your data is stored in a linear array or some fancy data structure, as long as it looks like a List<String>.
On the other hand, reading the second line gives you the idea that the code cares about the variable being ArrayList<String>. By writing this, you are implicitly saying (to future readers) that you shouldn't blindly change actual object type because the rest of the code relies on the fact that it is really an ArrayList<String>.
Using the interface allows you to quickly change the underlying implementation of the List/Map/Set/etc.
It's not about saving keystrokes, it's about changing implementation quickly. Ideally, you shouldn't be exposing the underlying specific methods of the implementation and just use the interface required.
I would suggest thinking about this from the other end around. Usually you want a List or a Set or any other Collection type - and you really do not care in your code how exactly this is implemented. Hence your code just works with a List and do whatever it needs to do (also phrased as "always code to interfaces").
When you create the List, you need to decide what actual implementation you want. For most purposes ArrayList is "good enough", but your code really doesn't care. By sticking to using the interface you convey this to the future reader.
For instance I have a habit of having debug code in my main method which dumps the system properties to System.out - it is usually much nicer to have them sorted. The easiest way is to simply let "Map map = new TreeMap(properties);" and THEN iterate through them, as TreeMap returns the keys sorted.
When you learn more about Java, you will also see that interfaces are very helpful in testing and mocking, since you can create objects with behaviour specified at runtime conforming to a given interface. An advanced (but simple) example can be seen at http://www.exampledepot.com/egs/java.lang.reflect/ProxyClass.html
if later you want to change implementation of the list and use for example LinkedList(maybe for better performance) you dont have to change the whole code(and API if its library). if order doesnt matter you should return Collection so later on you can easily change it to Set if you would need items to be sorted.
The best explanation I can come up with (because I don't program in Java as frequently as in other languages) is that it make it easier to change the "back-end" list type while maintaining the same code/interface everything else is relying on. If you declare it as a more specific type first, then later decide you want a different kind... if something happens to use an ArrayList-specific method, that's extra work.
Of course, if you actually need ArrayList-specific behavior, you'd go with the specific variable type instead.
The point is to identify the behavior you want/need and then use the interface that provides that behavior. The is the type for your variable. Then, use the implementation that meets your other needs - efficiency, etc. This is what you create with "new". This duality is one of the major ideas behind OOD. The issue is not particularly significant when you are dealing with local variables, but it rarely hurts to follow good coding practices all the time.
Basically this comes from people who have to run large projects, possibly other reasons - you hear it all the time. Why, I don't actually know. If you have need of an array list, or Hash Map or Hash Set or whatever else I see no point in eliminating methods by casting to an interface.
Let us say for example, recently I learned how to use and implemented HashSet as a principle data structure. Suppose, for whatever reason, I went to work on a team. Would not that person need to know that the data was keyed on hashing approaches rather than being ordered by some basis? The back-end approach noted by Twisol works in C/C++ where you can expose the headers and sell a library thus, if someone knows how to do that in Java I would imagine they would use JNI - at which point is seems simpler to me to use C/C++ where you can expose the headers and build libs using established tools for that purpose.
By the time you can get someone who can install a jar file in the extensions dir it would seem to me that entity could be jus short steps away - I dropped several crypto libs in the extensions directory, that was handy, but I would really like to see a clear, concise basis elucidated. I imagine they do that all the time.
At this point it sounds to me like classic obfuscation, but beware: You have some coding to do before the issue is of consequence.