How are List and List<String> different? - java

I'd just started working with lists and wanted to know how both of these are different?
Im guessing the second one specifically points out that it contains only string type stuff, while the first one is more flexible.
But then if the first is more flexible, why do people use the second one ever?

It's called generics.
The second one specifies this is a list of Strings and will throw a compiler error if you try to put something else.
It is useful to prevent people from putting anything besides a String in the List.
Here is a link to the java generic tutorial.

List<E> : Its generic and E will be any object i.e it will contain List of Object.
List<String> : The data type of list is string i.e it can only contain String.
It depend on the requirement what is the need of datatype of List.May be whatever example you looked require list of String.

Related

How to assign accepted objects to generics?

Is it possible to set several object to List?
If I declare List<Object> it will accept any kind of objects.
If I declare List<Integer> it will accept only integers.
Can I make a list which will accept Integers OR Floats and nothing else?
Is it possible to set several object to List?
Yes you can do that by declaring list as List<Object>
Can i make a list wich will accept Integers OR Floats and nothing else?
There is no direct way to accept only two type.
Possible ways of doing it is
1) Take individual lists (preferred)
2) Take List of type Object. And use insatanceof key words while
using it.
3) Implementing your own list and override add() method. While
adding to that list check type of instance and if it is not desired,
throw Exception.
To simulate a list which can hold integer or float values I would probably use an "Either" type.
While java doesn't provide it automatically, stackoverflow can help with a good enough implementation:
How can I simulate Haskell's "Either a b" in Java
so you would have:
List<Either<Integer,Float>> list;
You can get a support from This tutorial, And you can read the java documentation as well.
There is a thread also here.

What is the use of singletonList?

I was looking around for some elegant solution to removing null values from a List. I came across the following post, which says I can use list.removeAll(Collections.singletonList(null));
This, however, throws an UnsupportedOperationException, which I'm assuming is because removeAll() is attempting to do some mutative operation on the immutable singleton collection. Is this correct?
If this is the case, what would be a typical use of this singletonList? To represent a collection of size 1 when you're sure you don't want to actually do anything with the collection?
Thanks in advance.
It works like a charm:
List<String> list = new ArrayList<String>();
list.add("abc");
list.add(null);
list.add("def");
list.removeAll(Collections.singletonList(null));
System.out.println(list); //[abc, def]
Indeed Collections.singletonList(null) is immutable (which is unfortunately hidden in Java[1]), but the exception is thrown from your list variable. Apparently it is immutable as well, like in example below:
List<String> list = Arrays.asList("abc", null, "def");
list.removeAll(Collections.singletonList(null));
This code will throw an UnsupportedOperationException. So as you can see singletonList() is useful in this case. Use it when client code expects a read-only list (it won't modify it) but you only want to pass one element in it. singletonList() is (thread-)safe (due to immutability), fast and compact.
[1] E.g. in scala there is a separete hierarchy for mutable and immutable collections and API can choose whether it accept this or the other (or both, as they have common base interfaces)
To answer your actual question :
what would be a typical use of this singletonList? To represent a collection of size 1 when you're sure you don't want to actually do anything with the collection?
The typical use is if you have one element and want to pass it to a method that accepts a List, ie
public void registerUsers(List<User> users) {...}
User currentUser = Login Manager.getCurrentUser();
registerUsers(Collections.singletonList(currentUser));
The removeAll() is a special case for this.
Has your list been protected with
Collections.unmodifiableList(list)
Because if you have protected it and try to modify it later you get that error.

Adding values to Arraylist

Code 1:
ArrayList arr = new ArrayList();
arr.add(3);
arr.add("ss");
Code 2:
ArrayList<Object> arr = new ArrayList<Object>();
arr.add(3);
arr.add("ss");
Code 3:
ArrayList<Object> arr = new ArrayList<Object>();
arr.add(new Integer(3));
arr.add(new String("ss"));
all the above three codes are working fine.. can some one tell me the which is prefered and why.. and why the eclipse compiler always gives warning when type of arguments are not mentioned to the Arraylist.. thanks in advance..
First simple rule: never use the String(String) constructor, it is absolutely useless (*).
So arr.add("ss") is just fine.
With 3 it's slightly different: 3 is an int literal, which is not an object. Only objects can be put into a List. So the int will need to be converted into an Integer object. In most cases that will be done automagically for you (that process is called autoboxing). It effectively does the same thing as Integer.valueOf(3) which can (and will) avoid creating a new Integer instance in some cases.
So actually writing arr.add(3) is usually a better idea than using arr.add(new Integer(3)), because it can avoid creating a new Integer object and instead reuse and existing one.
Disclaimer: I am focusing on the difference between the second and third code blocks here and pretty much ignoring the generics part. For more information on the generics, please check out the other answers.
(*) there are some obscure corner cases where it is useful, but once you approach those you'll know never to take absolute statements as absolutes ;-)
The second one would be preferred:
it avoids unnecessary/inefficient constructor calls
it makes you specify the element type for the list (if that is missing, you get a warning)
However, having two different types of object in the same list has a bit of a bad design smell. We need more context to speak on that.
The second form is preferred:
ArrayList<Object> arr = new ArrayList<Object>();
arr.add(3);
arr.add("ss");
Always specify generic arguments when using generic types (such as ArrayList<T>). This rules out the first form.
As to the last form, it is more verbose and does extra work for no benefit.
Actually, a third is preferred:
ArrayList<Object> array = new ArrayList<Object>();
array.add(Integer.valueOf(3));
array.add("ss");
This avoids autoboxing (Integer.valueOf(3) versus 3) and doesn't create an unnecessary String object.
Eclipse complains when you don't use type arguments with a generic type like ArrayList, because you are using something called a raw type, which is discouraged. If a class is generic (that is, it has type parameters), then you should always use type arguments with that class.
Autoboxing, on the other hand, is a personal preference. Some people are okay with it, and some not. I don't like it, and I turn on the warning for autoboxing/autounboxing.
You are getting the warning because ArrayList is part of java generics. Essentially, it's a way to catch your type errors at compile time. For example, if you declare your array list with types Integer (ArrrayList<Integer>) and then try to add Strings to it, you'll get an error at compile time - avoiding nasty crashes at runtime.
The first syntax is there for backward compatibility and should be avoided whenever possible (note that generics were not there in older versions of java).
Second and third examples are pretty much equivalent. As you need to pass an object and not a primitive type to add method, your 3 is internally converted to Integer(3). By writing a string in double-quotes you effectively are creating a String object. When calling String("ss") you are creating a new String object with value being the same as the parameter ("ss").
Unless you really do need to store different types in your List, I would suggest actually using a proper type declaration, e.g. ArrayList<Integer> = new ArrayList<Integer>() - it'll save you a lot of headache in the long run.
If you do need multiple datatypes in the list, then the second example is better.
Two last variants are the same, int is wrapped to Integer automatically where you need an Object. If you not write any class in <> it will be Object by default. So there is no difference, but it will be better to understanding if you write Object.
Well by doing the above you open yourself to run time errors, unless you are happy to accept that your arraylists can contains both strings and integers and elephants.
Eclipse returns an error because it does not want you to be unaware of the fact that by specifying no type for the generic parameter you are opening yourself up for run time errors. At least with the other two examples you know that you can have objects in your Arraylist and since Inetegers and Strings are both objects Eclipse doesn't warn you.
Either code 2 or 3 are ok. But if you know you will have either only ints or only strings in your arraylist then I would do
ArrayList<Integer> arr = new ArrayList<Integer>();
or
ArrayList<String> arr = new ArrayList<String>();
respectively.
There's a faster and easy way in Java 9 without involving much of code: Using Collection Factory methods:
List<String> list = List.of("first", "second", "third");
in the first you don't define the type that will be held and linked within your arraylist construct
this is the preferred method to do so, you define the type of list and the ide will handle the rest
in the third one you will better just define List for shorter code

Returning two different values from method

I have method that parses a list of String records into objects and returns List of objects. So my method signature is like this.
public List<ParsedObject> parse(String[] records);
But I also want to return, other metrics like number of string records that were not parsed successfully. Now I get confused, how to return this metric. One option would be to create another wrapper class that holds both list of parsed records and members to store these metrics.
But I face this situation very often and this way I would end up in creating many wrapper classes.
Not sure if I explained well. Any suggestions here?
Java does not support returning multiple values from a function, unfortunately. You can create a wrapper class, like you said. Another option is to pass in an array of integers or a "metrics" object or something like that and modify it inside Parse. Slightly better might be to have one or more instance variables (rather than method variables) to keep track of any sort of diagnostic information you need.
Your question has already been discussed (see this for example: Should Java method arguments be used to return multiple values? ). I personally think that you should either make two method calls, if the returned data is not related. If they are, then you should create a "wrapper" class as you call it. If they really are related data then they probably belong in the same class anyway.
I don't personally favor modifying passed in objects because to me it is a side effect, and it is not clear to see what the method really does.
Another way to think of it is to use the factory pattern (see http://en.wikipedia.org/wiki/Factory_method_pattern) if the object you are building is complex.
Create a ParseResult object. You could include the List, number of records parsed, errors, etc. Make it generic enough so that it could be returned from different methods. You could even make it a base class and return classes that extend from it. Just keeping thinking in terms of objects.
You can return a complex object containing the list and all the information you need.
Maybe this could help http://www.yoda.arachsys.com/java/parameters.html
I was going to suggest to you some kind of 'c++ pair' type, but then I found this: What is the equivalent of the C++ Pair<L,R> in Java?
A wrapper class is the standard way of returning more information from a function. Another alternative would be to pass another parameter by reference and modify it in your function, thus effectively returning new information to the caller. For example, in your case you would pass an empty list and add all the parsed elements in that list. The return type could be a metric or an error code. Thus the caller will have both pieces of information.
This is a very common problem for many people who develop using Java. In other languages, such as Scala, one can create tuples, which are anonymous objects which can hold multiple values, and use them as arguments or return values.

What is the Collections.checkedList() call for in java?

I just want to know for what java.util.Collections.checkedList() is actually used.
I have some code that I know is returning me a List<String> but it's being passed through a chain of messaging calls and returned to me as a java.io.Serializable. Is that checkedList call good for me to turn my Serializable into a List<String>? I know I can cast it to a java.util.List, but I'd rather not have to check each element and I'm not comfortable with assuming each element is a String.
It is used in part as a debugging tool to find where code inserts a class of the wrong type, in case you see that happening, but can't figure out where.
You could use it as part of a public API that provides a collection and you want to ensure the collection doesn't get anything in it of the wrong type (if for example the client erases the generics).
The way you could use it in your case is:
Collections.checkedList(
new ArrayList<String>(uncertainList.size()), String.class)
.addAll(uncertainList);
If that doesn't throw an exception, then you know you are good. That isn't exactly a performance optimized piece of code, but if the list contents are reasonably small, it should be fine.
Not quite:
Collections.checkedList will only decorate the list to prevent any future inserts with objects of the wrong class, it won't check all the elements that are already in the list.
However, you could make a new checkedList, and then call addAll and pass in the list you are unsure about - rather than writing the loop yourself.
A discussion of what checkedList could be used for is available in the documentation for checkedCollection. The reasons given are:
as a debugging aid (if someone has used an unchecked cast)
to ensure safety when passing a collection to be populated by third-party code.
You could use the following from google collections to check that the list does only contain strings:
Iterables.all(list, Predicates.instanceOf(String.class))

Categories

Resources