Getting objects in linked lists vs. arrays in java - java

Ok so this is probably a very beginner question but...
Right now I have an object called Person with a method on it called setName
I am in my main class and I have declared
List People = new LinkedList();
What I want to do is simply call the setName function of the object in the first position.
I have found that this is very easy to do when working with an array of People. All I would do would be to say
People[0].setName("steve");
But since it is in a linkedlist I am having troubles.
I tried using the "get" method like so...
People.get(0)
but then it doesn't allow me to use my user defined methods so I can't set the name.
What is the best way to get an object out of a linked list and access its methods and instance variables?
thanks in advance

You want to use generics to make it a list of people:
List<Person> People = new LinkedList<Person>();
People.get(0).setName("steve");

Use generics:
List<Person> people = new LinkedList<Person>();
// …
people.get(0).setName("steve");

You should use generics: List<Person>. Then you would be able to use people.get(0).setName(..)
Note that Java naming convention requires your variable to be lowercase.

You dont set which type of objects you store. So you need upcast:
Person person = (Person)People.get(0);
person.setName("steve");
or set type of stored objects:
List<Person> people = new LinkedList<Person>();

LinkedList is only good when you want to iterate quickly over the list, and when you want to quickly get to the first or last element. Also, you need to properly define people as a LinkedList to have access to the linked list methods, and you should type your list, so:
LinkedList<Person> people = new LinkedList<Person>();
people.getFirst().setName();
However, ArrayList is a better general choice, which offers good performance when accessing elements by their index, so:
List<Person> people = new ArrayList<Person>();
then
people.get(0).setName("fred");

If using Java 1.4 or earlier you need to cast it to People class:
((Person)People.get(0)).setName("SomeName");
If using Java 1.5 or later use generics:
List<Person> people = new LinkedList();

You need to define the Linked list as a Person LinkedList:
LinkedList<Person> people = new LinkedList<Person>();
people.get(0).setName("Steve");
Another note(not about the question, just to improve your Java): You use lowercase on the first letter of variable names, because of Java conventions and any subsequent word's first letter are capitalized;
float personsAge = 57.47;
EXPLANATION(Ignore if easily bored):
The LinkedList was not set to store a specific variable type.
Another way to have solved this problem would have been:
LinkedList people = new LinkedList();
Person person = (Person) people.get(0);
person.setName("steve2")
Although you would have to do this to each 'Person' in the people list, defeating the point of the LinkedList.

Related

When do I need to create new instance of the List?

When do I need to choose one or the other method for lists? What about the resources we use?
List<String> names = new ArrayList<>(something.getList);
List<String> names = something.getList;
Doing this List<String> names = something.getList; assigns another reference to the something.getList object namely names. With the other syntax you get a brand new names object. As for which to use, is it actually a question of what you need, if you need to pass around a list i'd suggest you to use an Immutable List.
This is the preferred way to do things, it means later on you can change the List of names to be of a different implementation of List because List is the interface and ArrayList is the comcrete implementation. Later in life you may want to change this to be a LinkedList or other implementation that uses the List interface.
I would do like this:
List<String> names = new ArrayList<String>(something.getList());

What class to use for ArrayList?

I just wanted to clarify this question I had for a while for more efficient and 'correct' code.
I gave a class 'Student' with objects in an array list of objects. I have another class called Class which has an array list of references to the very same objects in the Student class.
Should I declare the 'Class' class as
ArrayList<Student> myStudents = new ArrayList<Student>();
or
ArrayList<Class> myStudents = new ArrayList<Class>();
Also another part of the question is I have seen people declare arrayLists as ArrayList<Student> myStudents = new ArrayList<>();
where the second half of the carrots are left empty. What exactly does the difference mean? Does this mean that the array list is not an object of any class?
Thank you so much for your time and help
Cheers
It depends on what you want to store in the list rather than where you are using it. If you're storing Student objects, then you'll use ArrayList<Student>().
The type omitted on the right side is called type inference (added in java 7), which means the type parameter on the right side will be inferred from the type of the assignment variable on the left. It helps to write the code in a cleaner way. For e.g.
Writing below is easier:
List<Some<Type<Another>>> var = new ArrayList<>();
than:
List<Some<Type<Another>>> var = new ArrayList<Some<Type<Another>>>();
Technically, neither.
You would want to do:
List<Student> myStudents = new ArrayList<>();
if you want to create an ArrayList with Student objects and
List<Class> myClasses = new ArrayList<>();
if you want to create an ArrayList with Class objects.
1) Note the variable names.
2) Note that you should always try to code to an interface (the left side is a List, not an ArrayList). This allows much greater flexibility since you're not dependent on the specific implementation of an ArrayList later on. This point is so powerful! You can write method signatures to accept objects of type List and then use an ArrayList, LinkedList or Stack or any class that implements a List. Depending on how you are using your ArrayList later, the Collection interface may be sufficient instead.
The diamond operator allows the compiler to infer the value of the type argument without having to type it all out. It's needed for backward compatibility for older Java versions.
As a general practice for performance optimization, you will also want to supply an initial capacity of an ArrayList if it's possible. So if you know that there are only 5 classes, then you would do:
List<Class> myClasses = new ArrayList<>(5);

Declaring a LinkedList in Java

I always learn when we declare a collection we should do, Interface ob = new Class(), if i want to use for example a LinkedList i'll do List ob = new LinkedList(), but then i can't have access to all methods from LinkedList.. Isn't LinkedList ob = new LinkedList() 100% correct?
Isn't LinkedList ob = new LinkedList() 100% correct?
Well I'd suggest using the generic form, but sure - if you want to use functionality which is specific to LinkedList, you need to declare the variable accordingly.
You might want to check whether the Deque<E> or Queue<E> interfaces have what you want though. If they do, use those in-keeping with the idea of describing what you need rather than what implementation you'll use.
Yes,
LinkedList<...> items = new LinkedList<...>();
is perfectly correct if you know that items will depend on methods of LinkedList<T> that are not captured in the List<T> interface.
You should always try to keep the declaration at the highest level possible, meaning that you should stop at the highest level that provides all the functionality that you need: if List methods are not enough, you're perfectly fine with your LinkedList declaration.
If you actually have a need to use methods that are not on the List interface, there is certainly nothing wrong with using LinkedList's API. The general rule of programming to the List interface recognizes that 1) it's pretty rare to need those methods, and 2) in most people's experience, it's way more likely that I discover I need to sort the list and/or use a lot of random access, and decide to switch to an ArrayList, than it is I need one of the methods only LinkedList has.
It may be also that you could be programming to the Queue interface, if you find List isn't giving you what you need.
The rule "always code to interfaces" must be taken with some flexibility. What you are suggesting is fine, and as you came to the conclusion, the only option.
As a side note, coding to concrete classes like this is faster is most JVMs. Deciding whether the performance is worth breaking the rule is the hard thing to decide.
LinkedList is a generic. You should be doing:
LinkedList<String> linkedList = new LinkedList<String>();
(or whatever else you need to store in there instead of String)
Not exactly 100% correct.
A preferred way to declare any collection is to include the data type it's holding. So, for your example, it'd be LinkedList<Integer> ob = new LinkedList<Integer>();.
Nope.. This would be wrong, at the later stages if he wants to change his implementation from linked list to any other implementation of list type he will go wrong... So better to use the interface level declaration.
I won't always suggest you to use generics .....
Coz sometimes you may need to wrap different objects as here....
String str="a string";
boolean status=false;
LinkedList ll = new LinkedList();
ll.add(str);
ll.add(status);
In some situations like case of RMI, u can only send serialized data.....and suppose you want to send a class object(which is unserialized).......There you can wrap the members of the class(primitives) in a LinkedList and pass that object as a whole.......not worrying about the huge number of arguments......
Consider for eg:
public Class DataHouse
{
public int a;
public String str;
.
.
.
}
Now Somewhere u need to pass the objects....
You can do the following....
DataHouse dh =new DataHouse();
LinkedList ll = new LinkedList();
ll.add(dh.a);
ll.add(dh.str);
// Now the content is serialized and can pass it as a capsuled data......
you can still have access to LinkedList methods by using List, all you have to do is to type cast
for example
((LinkedList)ob).add()
The point of using generic List and not LinkedList is because in case you simply change the type of lists you are using (let's say double linked list) your program will still work Generics are to simplify your code to be more portable and more "changeable"
Actually it would be better if it would be parametrized as both are raw types.

Placing a List in the parameters of another List in java

Sorry if the title is unclear, but I wasn't exactly sure how to describe this in that little amount of words. Okay, so suppose we have this declaration:
ArrayList<String> list = new ArrayList<String>();
//add items to list
Set<String> set = new TreeSet<String>(list);
Now, from what I understand, set will receive the data from list and sort them because that's what TreeSets do. However, on the oracle website, I don't see any constructor in the HashSet class that takes a List as a parameter. So, I don't understand why this works if there is no defined constructor to accept a List as a parameter.
TreeSet has a constructor that takes a Collection, and List is a Collection (List extends Collection).
Many classes in the Java collections framework follow the same concept. ArrayList, for instance, also has a constructor that takes a Collection. This makes it easy to copy data between collections.
Take a look at TreeSet(Collection c). This accepts a Collection and ArrayList implements Collection.

How to create a new list of same type as old list in Java?

I'm trying to write a method that takes in a List and create a new List of the same type based on it. That is, if the input list is an ArrayList, then I want the method to create a new ArrayList. The problem is that the program won't know if the List is an ArrayList or a LinkedList until runtime.
So far I've tried using the clone() method, but I don't think it works because the List class doesn't have clone() defined, and when I cast the input list as an Object and then clone then recast as a List, it also doesn't work (I'm not sure why).
All the standard lists from the JDK support clone, so
List copy = (List)((Cloneable)somelist).clone()
should work fine.
of course you can use reflection
Class c = somelist.getClass();
List newlist = (List)c.newInstance();
newlist.addAll(somelist);
Can you say more about why you want to do this? Without a good rationale, I'd contend:
Consider not doing this at all, but instead:
static <T> List<T> cloneMyList(final List<T> source)
{
return new ArrayList<T>(source);
}
If what you REALLY want is an efficient way to create a second copy of a known list, maybe the underlying implementation type really doesn't matter. In that case, just use an ArrayList which can be efficiently allocated using the List copy constructor.
Here it is:
List<YourType> destinationList = new ArrayList<>(sourceList.size());
Collections.copy(destinationList, sourceList);

Categories