General use of Linked List - java

I know you can create your own Linked List class or import one with java.util.
Like so :
import java.util.*;
LinkedList<String> ll=new LinkedList<String>();
and then do some stuff to the list with the already existing methods, like add, get, set...
But you can also create your own Linked List liked that :
class LinkedList {
Node head; // head of list
class Node {
int data;
Node next;
Node(int d) { data = d; }
}
}
But if you're doing it like that you need to create all of the methods.
My question is pretty simple, should I use method 1 or 2 ? And if both are fine when would it be better to use one over another.

If you need a general-purpose List, use java.util.LinkedList. It's a standard class, mature, well-tested, well-understood by almost any Java dev... and, ofc, it's concise, because you don't have to implement it.
Actually, don't use it: use java.util.ArrayList or java.util.ArrayDeque, they out-perform LinkedList in almost all circumstances. See When to use LinkedList over ArrayList in Java?
If you really need something more specialized, implement your own, but only if you really, really need it.
Only make your class implement java.util.List if you actually need it to.
A good starting point to avoid having to implement "everything" in the interface is to extend java.util.AbstractList: this only requires you to provide an implementation of get(int), size() and, if you want the list to be modifiable, set(int, E) (you may well want to override others to get better performance for a linked list).

Don't reinvent the wheel unless you need something extremely specific that the existing wheel doesn't provide.
Also, might be worth mentioning that linked lists have poor performance characteristics since the memory they occupy isn't continuous, causing the multiple reads from main memory (link).

Related

Java LinkedList class

In class, I've implemented my own LinkedList class with a private Node class so I've never run into this issue before. But now I'm trying to re-do a problem using Java's built-in LinkedList library and am running into trouble. (its also been a few years since I last used Java).
Lets say I had this simple skeleton. How would I pass the head Node into the function?
public static void main(String[] args)
{
LinkedList<Integer> test = new LinkedList<Integer>();
doSomething(test.get(0));
}
private static void doSomething(Node a)
{
//stuff
}
Also could someone remind me what the difference is between these two? I know the first you're basically casting the list as a LinkedList but why do so?
List<E> test = new LinkedList<E>();
LinkedList<E> test = new LinkedList<E>();
Looking at the documentation for LinkedList, there are no methods that expose the nodes of the list. In fact, LinkedList might even be implemented in a completely different way and not use nodes at all and still have all the properties and performance guarantees of a linked list. It's an implementation detail.
The standard library LinkedList class uses encapsulation to avoid exposing implementation details (like how list nodes are implemented) to the user of the class (you).
There is no way you can get a reference to the internal list node, save for using advanced techniques like reflection that break encapsulation.
Instead of playing around with list nodes and pointers between them, you use the methods the LinkedList class provides to add and retrieve the list elements. For example:
LinkedList<Integer> test = new LinkedList<Integer>();
test.add(314);
test.add(879);
Integer first = test.getFirst(); // returns 314
Integer first = test.get(1); // returns 879
The benefit from encapsulation is that JVM implementors are free to change the internal implementation of LinkedList completely without fear of breaking your program.
You get the same benefit in your own program if you use the List interface instead LinkedList class by writing:
List<E> test = new LinkedList<E>();
If you do this, you are free to change test from LinkedList to ArrayList or any other list implementation at a later point with no other changes to the code, for example if the application requirements change or if you find that ArrayList gives you better performance.
Java's native linked class has some issues. Iterators can be used to access nodes, but are limited as noted below. There is no way to move nodes within a list or from list to list, such as C++ std::list::splice.
https://en.cppreference.com/w/cpp/container/list/splice
For Java, "moving" nodes requires removing and inserting nodes, which involves deallocation for any node removed, and allocation for any node inserted.
Java's iterators can't be shallow copied. An assignment just sets another variable to point to the same iterator object. (C++ iterators don't have this issue).
Any removal or insertion of nodes from a list will invalidate all iterators to that list (except for the iterator used to do the remove or insert). (C++ iterators function as expected).

Should I implement List interface or extend ArrayList class

I am developing an application where as a background I need to monitor the user activity on particular objects and later when they are visualized they need to be sorted based on the order of which the user used them ( the last used object must be visualized on the first row of a grid for example.)
So if I have an ArrayList where I store the objects which the user is dealing with in order to add the last used object I need to check if it is already in the list and then move it at the first position. If the object is not there I simply add it at the first position of the list.
So instead of doing all these steps I want to make my own list where the logic explained above will be available.
My question is which scenario is better:
Implement the list interface
Extend the ArrayList class and override the ADD method
Create a class that contains an ArrayList and handles any additional functionality.
I.e. prefer composition over inheritance (and in this case, implementing an interface). It's also possible to have that class implement List for relevant cases and just direct the (relevant) operations to the ArrayList inside.
Also note that LinkedHashMap supports insertion order (default) and access order for iteration, if you don't need a List (or if you can suitably replace it with a Map).
So instead of doing all these steps i want to make my own list where
the logic explained above will be available.
I would try to refactor your design parameters (if you can) in order to be able to use the existing Java Collection Framework classes (perhaps a linked collection type). As a part of the Collections Framework, these have been optimized and maintained for years (so efficiency is likely already nearly optimal), and you won't have to worry about maintaining it yourself.
Of the two options you give, it is possible that neither is the easiest or best.
It doesn't sound like you'll be able to extend AbstractList (as a way of implementing List) so you'll have a lot of wheel reinvention to do.
The ArrayList class is not final, but not expressly designed and documented for inheritance. This can result in some code fragility as inheritance breaks encapsulation (discussed in Effective Java, 2nd Ed. by J. Bloch). This solution may not be the best way to go.
Of the options, if you can't refactor your design to allow use of the Collection classes directly, then write a class that encapsulates a List (or other Collection) as an instance field and add instrumentation to it. Favor composition over inheritance. In this way, your solution will be more robust and easier to maintain than a solution based on inheritance.
I think LinkedHashMap already does what you need - it keeps the elements in the order they were inserted or last accessed (this is determined by the parameter accessOrder in one of the constructors).
https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashMap.html
EDIT
I don't have enough reputation to comment, so I'm putting it here: You don't actually need a map, so Venkatesh's LinkedHashSet suggestion is better.
You can do something like this:
<T> void update(Set<T> set, T value) {
set.remove(value);
set.add(value);
}
and then
LinkedHashSet<String> set = new LinkedHashSet<>();
update(set, "a");
update(set, "b");
update(set, "c");
update(set, "a");
Iterator<String> it = new LinkedList<String>(set).descendingIterator();
while (it.hasNext()) {
System.out.println(it.next());
}
Output:
a
c
b
You might try using HashMap<Integer, TrackedObject> where TrackedObject is the class of the Object you're keep track of.
When your user uses an object, do
void trackObject(TrackedObject object)
{
int x = hashMap.size();
hashMap.add(Integer.valueOf(x), object);
}
then when you want to read out the tracked objects in order of use:
TrackedObject[] getOrderedArray()
{
TrackedObject[] array = new TrackedObject[hashMap.size()];
for(int i = 0; i < hashMap.size(); i++)
{
array[i] = hashMap.get(Integer.valueOf(i));
}
return array;
}
A LinkedHashSet Also can be helpful in your case. You can keep on adding elements to it, it will keep them in insertion order and also will maintain only unique values.

Putting two linkedlists together without copying - Java, Using standard API [duplicate]

This question already has answers here:
Merge two lists in constant time in Java
(4 answers)
Closed 9 years ago.
I have two LinkedList in my code and I need to make one that have both. I will not need this Lists anymore, just the new one, which have all data I need.
I could use .addAll(), but performance is I huge issue and I cant wait to copy,adding references, everything every time..
I am looking for something like we normally do if we create our own linkedlist, just connect the last node from one to the fist from the second.. Is there a way to do that using the LinkedList class from the java api?
Merging collections is a different case, although the operation means almost the same, my issue is just regarding performance and just for linkedlists, which normally can do what I need. Also "merging" is kind of an ambiguous term, what I want is just to put then together no matter what order they are, with performance in mind.I am not looking if is possible to merge...
Another thing, my question is just regarding the API, I am not looking for building my own code (boss requirement) and that is why is different from this one: Merge two lists in constant time in Java - not useful answers there either..
If you are using LinkedList then you are most likely not interested in indexed access (since indexed access is slow... but keep in mind that a list only stores references, so for very large lists with few insert/removes you are going to be more memory efficient with an ArrayList as it doesn't need to allocate each node on the heap)
So what you actually want is something that gives you most of the List contract... or maybe not even that.
It could well be that all you want is something that gives you Iterable<String>... if that is the case then you have a very easy life:
public class UberIterable<T> implements Iterable<T> {
private final List<List<T>> lists;
public UberIterable(List<T>... lists) {
this.lists = Arrays.asList(lists);
}
public Iterator<T> iterator() {
return new Iterator<T>() {
Iterator<List<T>> metaNext = lists.iterator();
Iterator<T> next;
public boolean hasNext() {
while (true) {
if (next != null && next.hasNext()) return true;
if (metaNext.hasNext()) next = metaNext.next(); else return false;
}
}
public T next() {
if (!hasNext()) throw new NoSuchElementException();
return next.next();
}
public void remove() {
throw new UnsupportedOperation();
}
}
}
}
That is a basic implementation that will give you a merged view of many lists. If you want to get more of the contract of List you could repeat the same tricks only with a better implementation of ListIterator which will get a lot of what you are probably after, or finally by extending AbstractList and overriding the appropriate methods with your new ListIterator implementation
If you only want to iterate over the new list and you can replace List with Iterable you can use Guava's Iterable.concat as described here:
Combine multiple Collections into a single logical Collection?
I'm afraid the answer is no. The internal Entry class used by LinkedList is private, and all the public methods exposed by LinkedList work with general collections.
Your use case seems reasonable to me, but this implementation doesn't support it.
I'm afraid that the only way to do this is by using reflections... When you take a look at the source code of LinkedList, you can see that the subclass Entry<E> is private, which is a problem if you want to connect the first and last entries to other entries, in order to merge the list.
Update: Even reflections are not safe (unless you add checks), because Oracle changed the name of the subclass Entry to Node and changed the order of arguments of the constructor! in JDK 7, which is stupid IMHO.
Dirty solution: Do a whole copy paste of the source code and change the private keywords to public. However, I'm not sure this is allowed by Oracle. Check their license.
One way you could go about doing this is by using getLast() to grab the last element off the one of the lists and then use addFirst() on the other in order to add it to the front.
As has been said here, however, addAll() would not be copying anything and could be used just as easily.
If your issue is with the actual instantiation of node objects in the LinkedList, you may need to implement your own version that exposes more of the implementation mechanisms in its API.
why not create a wrapper/proxy class that implements List and contains references to the 2 sublists, then implement the List methods (or at least the ones you need downstream) - a little bit of work but if copying either of the lists is really the issue sounds like it is worth it.
import java.util.LinkedList;
public class MergeLinkedList {
public static void main(String[] args) {
LinkedList<String> mainlist = new LinkedList<String>() ;
mainlist.add("A");
mainlist.add("B");
LinkedList<String> secondlist = new LinkedList<String>() ;
secondlist.add("C");
secondlist.add("D");
mainlist.addAll(secondlist);
System.out.println(mainlist);
}
}
O/P
[A, B, C, D]
you have to use addall();

Java data structures (simple question)

Say I want to work with a linked list in java. I thought that the best way to create one is by:
List list = new LinkedList();
But I noticed that this way I can only use methods on the list that are generic. I assume that the implementation is different among the different data structures.
So if I want to use the specific methods for linked list, I have to create the list by:
LinkedList list = new LinkedList();
What's the main reason for that?
Tnanks.
List is an interface that abstracts the underlying list implementation. It is also implemented by e.g. ArrayList.
However, if you specifically want a LinkedList, there is nothing wrong with writing LinkedList list. In fact, if you just pass it around as a list, people may (not knowing the implementation) unknowingly write algorithms like:
for(int i = 0; i < list.size(); i++)
{
// list.get(i) or list.set(i, obj)
}
which are linear on a random access list (e.g. ArrayList) but quadratic on a LinkedList (it would be preferable to use a iterator or list iterator). Java provides the RandomAccess marker interface so you can distinguish.
Of course, you can call these methods on a reference of type LinkedList too, but people should be more likely to consider the cost.
As a note, in .NET LinkedList does not implement IList for this reason.
The first idiom allows you to change the runtime type that list points to without modifying any client code that uses it.
What methods in LinkedList do you think you need that aren't in List? You can always cast for those.
But the whole idea behind interfaces is to shield clients from how the interface is implemented.
If you really need a LinkedList, so be it. But I prefer the first idiom, because most of the time I really just need List methods.
Every LinkedList is a List, too. That also means that you can do everything with a LinkedList that you can do with a List and that you can store a LinkedList as List. However, when you store it as List, you can only call methods of the LinkedList that a List also has.
By the way: This is not Generics. Generics are like this:
LinkedList<String> list = new LinkedList<String>();
List list = getSomeList();
Here you're saying that it's a list. You have no idea whether or not it's a LinkedList or an ArrayList or whatever. It is an abstract thing (I assume you mean "abstract" by the word "generic", since generics are a different thing entirely). Thus you can't treat it like it's an LinkedList -- you have to treat it like it's a List (which it is).
The fact that "you know" that it's a LinkedList is all well and good, and you can safely cast if you need to do it. But it might help to tell the compiler that it's a LinkedList, by declaring it as so, if it's always going to act as a LinkedList.

Java: ArrayList for List, HashMap for Map, and HashSet for Set?

I usually always find it sufficient to use the concrete classes for the interfaces listed in the title. Usually when I use other types (such as LinkedList or TreeSet), the reason is for functionality and not performance - for example, a LinkedList for a queue.
I do sometimes construct ArrayList with an initial capcacity more than the default of 10 and a HashMap with more than the default buckets of 16, but I usually (especially for business CRUD) never see myself thinking "hmmm...should I use a LinkedList instead ArrayList if I am just going to insert and iterate through the whole List?"
I am just wondering what everyone else here uses (and why) and what type of applications they develop.
Those are definitely my default, although often a LinkedList would in fact be the better choice for lists, as the vast majority of lists seem to just iterate in order, or get converted to an array via Arrays.asList anyway.
But in terms of keeping consistent maintainable code, it makes sense to standardize on those and use alternatives for a reason, that way when someone reads the code and sees an alternative, they immediately start thinking that the code is doing something special.
I always type the parameters and variables as Collection, Map and List unless I have a special reason to refer to the sub type, that way switching is one line of code when you need it.
I could see explicitly requiring an ArrayList sometimes if you need the random access, but in practice that really doesn't happen.
For some kind of lists (e.g. listeners) it makes sense to use a CopyOnWriteArrayList instead of a normal ArrayList. For almost everything else the basic implementations you mentioned are sufficient.
Yep, I use those as defaults. I generally have a rule that on public class methods, I always return the interface type (ie. Map, Set, List, etc.), since other classes (usually) don't need to know what the specific concrete class is. Inside class methods, I'll use the concrete type only if I need access to any extra methods it may have (or if it makes understanding the code easier), otherwise the interface is used.
It's good to be pretty flexible with any rules you do use, though, as a dependancy on concrete class visibility is something that can change over time (especially as your code gets more complex).
Indeed, always use base interfaces Collection, List, Map instead their implementations. To make thinkgs even more flexible you could hide your implementations behind static factory methods, which allow you to switch to a different implementation in case you find something better(I doubt there will be big changes in this field, but you never know). Another benefit is that the syntax is shorter thanks to generics.
Map<String, LongObjectClasName> map = CollectionUtils.newMap();
instead of
Map<String, LongObjectClasName> map = new HashMap<String, LongObjectClasName>();
public class CollectionUtils {
.....
public <T> List<T> newList() {
return new ArrayList<T>();
}
public <T> List<T> newList(int initialCapacity) {
return new ArrayList<T>(initialCapacity);
}
public <T> List<T> newSynchronizedList() {
return new Vector<T>();
}
public <T> List<T> newConcurrentList() {
return new CopyOnWriteArrayList<T>();
}
public <T> List<T> newSynchronizedList(int initialCapacity) {
return new Vector<T>(initialCapacity);
}
...
}
Having just come out of a class about data structure performance, I'll usually look at the kind of algorithm I'm developing or the purpose of the structure before I choose an implementation.
For example, if I'm building a list that has a lot of random accesses into it, I'll use an ArrayList because its random access performance is good, but if I'm inserting things into the list a lot, I might choose a LinkedList instead. (I know modern implementations remove a lot of performance barriers, but this was the first example that came to mind.)
You might want to look at some of the Wikipedia pages for data structures (especially those dealing with sorting algorithms, where performance is especially important) for more information about performance, and the article about Big O notation for a general discussion of measuring the performance of various functions on data structures.
I don't really have a "default", though I suppose I use the implementations listed in the question more often than not. I think about what would be appropriate for whatever particular problem I'm working on, and use it. I don't just blindly default to using ArrayList, I put in 30 seconds of thought along the lines of "well, I'm going to be doing a lot of iterating and removing elements in the middle of this list so I should use a LinkedList".
And I almost always use the interface type for my reference, rather than the implementation. Remember that List is not the only interface that LinkedList implements. I see this a lot:
LinkedList<Item> queue = new LinkedList<Item>();
when what the programmer meant was:
Queue<Item> queue = new LinkedList<Item>();
I also use the Iterable interface a fair amount.
If you are using LinkedList for a queue, you might consider using the Deque interface and ArrayDeque implementing class (introduced in Java 6) instead. To quote the Javadoc for ArrayDeque:
This class is likely to be faster than
Stack when used as a stack, and faster
than LinkedList when used as a queue.
I tend to use one of *Queue classes for queues. However LinkedList is a good choice if you don't need thread safety.
Using the interface type (List, Map) instead of the implementation type (ArrayList, HashMap) is irrelevant within methods - it's mainly important in public APIs, i.e. method signatures (and "public" doesn't necessarily mean "intended to be published outside your team).
When a method takes an ArrayList as a parameter, and you have something else, you're screwed and have to copy your data pointlessly. If the parameter type is List, callers are much more flexible and can, e.g. use Collections.EMPTY_LIST or Collections.singletonList().
I too typically use ArrayList, but I will use TreeSet or HashSet depending on the circumstances. When writing tests, however, Arrays.asList and Collections.singletonList are also frequently used. I've mostly been writing thread-local code, but I could also see using the various concurrent classes as well.
Also, there were times I used ArrayList when what I really wanted was a LinkedHashSet (before it was available).

Categories

Resources