while developing I was trying to return an empty List.
public Collection<?> getElements() {
// return elements
}
I searched for an easy way, my first idea was to create for example an ArrayList without any elements and return it. Like the following example:
public Collection<?> getElements() {
return new ArrayList<?>();
}
For me it is too much overhead for an empty list.
There is a really simple solution for the above described "problem":
public Collection<?> getElements() {
return Collections.EMPTY_LIST;
}
That returns an empty list.
Notice:
It returns an immutable object! You can use it only, if you need an object, which isn't editable.
Type-safety
In the case you want to get a type-safe list you should use the following example [1]:
List<String> s = Collections.emptyList();
Three kinds of interfaces are supported:
List:
List l = Collections.EMPTY_LIST;
List<String> s = Collections.emptyList();
Map:
Map m = Collections.EMPTY_MAP;
Map<String> ms = Collections.emptyMap();
Set:
Set s = Collections.EMPTY_SET;
Set<String> ss = Collections.emptySet();
Notice:
Implementations of this method need not create a separate XXX object
for each call. Using this method is likely to have comparable cost to
using the like-named field. (Unlike this method, the field does not
provide type safety.)
Related
I have a POJO class SearchResults, that contains 4 Strings (title, number, date, status) and then all the getter and setter methods for it.
In another class I populate an ArrayList<SearchResults> results, is there a way I can go through that list results and erase any elements that have a duplicate number?
I've tried populating a new ArrayList by first passing results into a LinkedHashSet but that didn't work.
ArrayList<SearchResults> noDup;
noDup = new ArrayList<SearchResults>(new LinkedHashSet<SearchResults>(results));
I've also tried doing a .remove(indexof()) but that didn't work either.
if(noDup.contains(new SearchResults("-1","","",""))){noDup.remove(noDup.indexOf(new SearchResults("-1","","","")));}
Any suggestions?
Edit:
The equals() method in SearchResults (wonr refers to the number)
#Override
public boolean equals(Object object){
if(object == null){
return false;
}
if(getClass() != object.getClass()){
return false;
}
SearchResults result = (SearchResults) object;
if((this.wonr == null) ? (result.wonr == null): this.wonr.equals(result.wonr)){
return false;
}
return true;
}
The suggestions for implementing hashCode and equals are possible options, but does this single number value truly define what it means for these objects to be equivalent in the general case? If not, defining equals and hashCode that way seems to be a hack.
Without altering the definition of equivalence, if in just this case you want to elminiate values with the same number value, there are other approaches you can try. You didn't give us the API for your SearchResult class, so I'll assume there's an accessible field named number.
One quick way is to use a TreeSet which defines its idea of equivalence based on an underlying comparison operation. Write a custom Comparator that only looks at the number field and you're good to go:
Java 8
List<SearchResult> allResultsWithDuplicates = // ... populated list
Comparator<SearchResult> comparator =
(left, right) -> Integer.compare(left.number, right.number);
Set<SearchResult> uniqueNumbers = new TreeSet<>(comparator);
uniqueNumbers.addAll(allResultsWithDuplicates);
As JB Nizet mentioned, if your SearchResult class has a getNumber accessor method you can use a function reference and eliminate the lambda expression defining Comparator:
Comparator<SearchReult> comparator = Comparator.comparing(SearchResult::getNumber);
Java 5-7
In earlier versions of Java you must implement the Comparator class yourself. Then it plugs into the code given above in exactly the same way. This example assumes there is a int getNumber() accessor method on your SearchResult class:
Comparator<SearchResult> comparator =
new Comparator<SearchResult>() {
#Override
public int compare(SearchResult sr1, SearchResult sr2) {
// Optional support for null arguments is left as
// an exercise for the reader.
return Integer.compare(sr1.getNumber(), sr2.getNumber());
}
};
Another way you can do it with Java-8 is this way:
1) Create set of unique numbers,
2) Iterate over your list and filter by this set:
Set<Integer> numbers = new HashSet<>();
List<SearchResult> noDups = listWithDups.stream()
.filter(sr -> numbers.add(sr.getNumber()))
.collect(Collectors.toList());
If you implemented equals() and hashCode() so that they just look at Number property you could build a Set<SearchResult> instead of a ArrayList<SearchResult> and you will implicitly get no duplicates (this is one of the properties of sets - they don't contain duplicates). You can still iterate over the entries in the set so you should have all the functionality you need.
Do a stream of our list and use filter method and collect to an other list.
I have two lists as follows
List<MyObject1> list1
List<Long> list2
The list2 is basically the list of Id's of MyObject1 which is a property in the object
Public Class MyObject1 implements Serializable{
private Long myObjId;
.....
.....
//other elements go here
public Long getMyObjId() {
return myObjId;
}
public void setMyObjId(Long myObjId) {
this.myObjId = myObjId;
}
I want to compare the two lists to check if all the objects in list1 are contained in list2
One way is to iterate over the list1, create a new list of Id's out of it and then use the containsAll method on it.
Is there a simpler way to achieve the same result?
In Java 8 you can write what you described: "One way is to iterate over the list1, create a new list of Id's out of it and then use the containsAll method on it." in one line as:
list1.stream().map(a -> a.getMyObjId()).collect(Collectors.toList()).containsAll(list2);
map converts a each MyObeject to an id by calling a.getMyObjectId and collect creates a list
as a result.
There are at least two conceptually different approaches:
One could collect the IDs in a list, and work on the resulting list
One could do the check on-the-fly
The first one would boil down to something like
boolean allIdsContained(List<MyObject> myObjects, List<Long> validIds) {
List<Long> ids = new ArrayList<Integer>();
for (MyObject m : myObjects) ids.add(m.getID());
return validIds.continsAll(ids);
}
The second one could be written as
boolean allIdsContained(List<MyObject> myObjects, List<Long> validIds) {
for (MyObject m : myObjects) {
if (!validIds.contains(m.getID()) {
return false;
}
}
return true;
}
Note that the method signature is the same in both cases, so you are free to change the implementation according to your needs. Particularly, if the list if validIds is large, then it could be more efficient to first convert it to a Set. (The contains method on a List is O(n), whereas on a Set, it is O(1)). Then the method could be implemented as
boolean allIdsContained(List<MyObject> myObjects, List<Long> validIds) {
Set<Long> set = new HashSet<Long>(validIds);
for (MyObject m : myObjects) {
if (!set.contains(m.getID()) {
return false;
}
}
return true;
}
In any case, all these methods could be written more concisely with Java 8 Lambdas, but I think that this should be an implementation detail, and should be hidden in such a helper method regardless of how it is implemented.
If I have a method like this (for simplicity assume integers):
public static List<Integer> doSomething(List<Integer> list) {
// logic here
}
and I need for my processing to create internally a new list which I will create and somehow populate and return to the caller, how can I do it since I don't know what type of list the caller passed in?
I don't want to return a List of different type that what the caller passed in.
E.g. If the caller passed a LinkedList and I don't want to return an ArrayList.
How can this issue best be approached?
You shouldn't tie your implementation to a particular implementation of List, the idea of using an interface is that, from the outside, it shouldn't matter what concrete class you're instantiating as long as it conforms to the List interface.
EDIT :
Anyway, here's a possible way:
List<Integer> lst1 = new ArrayList<Integer>();
Class<?> klass1 = lst1.getClass();
List<Integer> copy1 = (List<Integer>) klass1.newInstance();
System.out.println(copy1.getClass().getName());
> java.util.ArrayList
List<Integer> lst2 = new LinkedList<Integer>();
Class<?> klass2 = lst2.getClass();
List<Integer> copy2 = (List<Integer>) klass2.newInstance();
System.out.println(copy2.getClass().getName());
> java.util.LinkedList
As you can see in the console, the copies are instances of the same class as the original list.
If you can get away with just using one of those two output types, then you can do
if (inputList instanceof RandomAccess) {
// use an ArrayList
} else {
// use a LinkedList.
}
The RandomAccess interface is meant to indicate that the implementation allows O(1) get operations.
Marker interface used by List implementations to indicate that they support fast (generally constant time) random access. The primary purpose of this interface is to allow generic algorithms to alter their behavior to provide good performance when applied to either random or sequential access lists.
By doing this, your APIs allow clients to defend their inputs. They can pass in the result of Collections.unmodifiableList(...) and be sure that it isn't modified by other code.
If you really know the input is a mutable list, you can clone() the list, then clear() it. Both ArrayList and LinkedList have public clone() methods which can be accessed reflectively.
The best thing to do is to remove the list creation from the method. Have the caller decide how to create the list:
public static void doSomething(List<Integer> dest, List<Integer> src) {
You could use Class.newInstance to create a list of the passed in type:
public static List<Integer> doSomething(List<Integer> list)
{
List<Integer> newList = null;
try
{
newList = list.getClass().newInstance();
}
catch(InstantiationException e)
{
throw new RuntimeException(e);
}
catch(IllegalAccessException e)
{
throw new RuntimeException(e);
}
//Logic here
return newList;
}
#Test
public void test()
{
List<Integer> testList = new ArrayList<Integer>();
List<Integer> resultList = doSomething(testList);
Assert.assertEquals(testList.getClass(), resultList.getClass());
Assert.assertNotSame(LinkedList.class, resultList.getClass());
testList = new LinkedList<Integer>();
resultList = doSomething(testList);
Assert.assertEquals(testList.getClass(), resultList.getClass());
Assert.assertNotSame(ArrayList.class, resultList.getClass());
}
If you really, really care what kind of object comes out, I would include that as a parameter to the method, like:
<T extends List<Integer>> T doSomething(Class<T> returnType,List<Integer> v)
throws Exception
{
// constructors for your return will be tricky :)
// returnType.newInstance() will probably work.
T result = returnType.newInstance();
result.add(86); result.add(99);
return result;
}
I am trying to use the Iterables class to filter an ArrayList, but when I try to cast the result back to the original type I get a ClassCastException at runtime.
// domains is an ArrayList<Domain> which is defined earlier in the class
Iterable<Domain> temp = Iterables.filter(domains, new Predicate<Domain>() {
public boolean apply(Domain input) {
if (input.getName().toLowerCase().contains(filter.toString().toLowerCase())) {
return true ;
} else {
return false;
}
}
}) ;
ArrayList<Domain> filteredDomains = (ArrayList<Domain>) temp ; // Error occurs here
To be complete, I am trying to use this in an Android application with a target of 1.6.
temp is not an ArrayList<Domain>. It is an Iterable<Domain>.
If you absolutely need an ArrayList<Domain> (or a List<Domain> in general), then you need to take a slightly different approach.
First, use Collections2.filter() instead of Iterables.filter(): to produce temp and then create a new ArrayList from the resulting Collection:
Collection<Domain> temp = Collections2.filter(domains, myPredicate) ;
List<Domain> filteredDomains = new ArrayList<Domain>(temp);
But you should really think if you need a List or ArrayList and if a Collection is not enough for what you want. If an Iterable is sufficient (for example if you only iterate over the content), then you can even keep using Iterables.filter().
The real return type is an anonymous class that extends IterableWithToString - and we cannot cast that type to ArrayList.
Here's the implementation on grepcode.
Temp is an Iterable not an ArrayList. Further more an ArrayList is an Iterable but not vice versa. What if you had
Iterable<?> iterable = new HashSet<?>();
You can see why a class cast exception would happen here.
To create an ArrayList from the Iterable you would have to iterate over the iterable itself and add to a new ArrayList
List<Domain> filteredDomains = new ArrayList<Domain>();
for(Iterator<Domain> i = temp.iterator(); i.hasNext();){
filteredDomains.add(i.next());
}
If I have a rarely used collection in some class which may be instantiated many times, I may sometimes resort to the following "idiom" in order to save unnecessary object creations:
List<Object> list = null;
void add(Object object) {
if (list == null)
list = new ArrayList<Object>();
list.add(object);
}
// somewhere else
if (list != null)
for (Object object : list)
;
Now I was wondering if I couldn't eliminate those null checks using Collections.emptyList(), however then I would have to alter the if check in add() like so:
if (list == Collections.<Object>emptyList())
list = new ArrayList<Object>();
Is there a better way to handle this other than just allocating a new empty collection every time?
EDIT: just to be clear, I would like to use Collections.emptyList(), but the above check in add() is really really ugly... I was wondering if there's a better way to do it or even a whole other way of handling this.
in order to save unnecessary object creations
That's a really bad idea which will litter your code with == null checks and other handling of corner cases (and presumably end up in null pointer exceptions anyway)!
Now I was wondering if I couldn't eliminate those null checks using Collections.emptyList()
No, not really. emptyList() returns an empty list. You could do
if (list.equals(Collections.<Object>emptyList()))
but that will still throw a NullPointerException if list == null, so it's still not what you're after.
My recommendation: Always initialize the list to new ArrayList<Object>, or, if you for instance want to return an empty list from a method, use Collections.emptyList() instead. (This returns the same instance every time, so no unnecessary object creation there either.)
And then use .isEmpty() to check if a collection is empty or not.
The suggested answers are absolutely correct, just small tip - in Java 8 you can use the new Optional class to handle the case where the list instance is null, in a more functional approach.
For example, something like this:
public static List<String> addElement(List<String> list, String toAdd) {
List<String> newList = Optional.ofNullable(list).orElse(new ArrayList<>());
newList.add(toAdd);
return newList;
}
Following a tip in the comments, it's better to replace new ArrayList<>() with Collections.emptyList() in order to prevent the creation of a new instance of an empty ArrayList
public static List<String> addElement(List<String> list, String toAdd) {
List<String> newList = Optional.ofNullable(list).orElse(Collections.emptyList());
newList.add(toAdd);
return newList;
}
There is an emptyIfNull method in package org.apache.commons.collections4;. It returns an empty list if the one provided is null.
List<Object> list = CollectionUtils.emptyIfNull(list);
Here is what I use for a helper method in some of my code. Really works nicely in reducing the ton of null checks I'd normally have to place before iterating over lists. If you want a list that wouldn't be immutable then you can return a new list object instead of Collections.emptyList
/**
* Helper method to return an empty list if provided one is null.
*
* #param list the list
* #return the provided list or an empty one if it was null
*/
private static <T> List<T> emptyIfNull(List<T> list) {
if (list == null) {
return Collections.emptyList();
}
return list;
}
You then just use the helper method like so:
for (Object object : emptyIfNull(existingList)) { ... }
If the list object is null, then the helper method will return the static empty list and the contents of your loop will be skipped. This is a nice way to avoid having to create null checks wrapping any list iterations.
I've made the internals of the list be of type Object just for the example, but you'd obviously change this to be whatever makes the most sense for your usage.
emptyList() doesn't allocate an object each time.
I would create less of the object which contains the List so you can create the list every time.
What you can do is
private List<Object> list = Collections.emptyList();
private List<Object> listForWrite() {
return list.isEmpty() ? list = new ArrayList<Object>() : list;
}
void add(Object object) {
listForWrite().add(object);
}
// avoid creating an Iterator every time.
for (int i = 0, size = list.size(); i < size; i++) {
;
}
Here's a variation on using optional as #Stas suggested, but also using the isEmpty immutable collection as originally requested in the question:
public static List<String> addElement(List<String> list, String toAdd) {
List<String> newList = Optional.ofNullable(list).orElse(Collections.emptyList());
newList.add(toAdd);
return newList;
}
This approach is also the closest thing I can find to the nice ability in Javascript to use an empty array if the collection is null.
For example:
// no need to indent everything inside a null check of myObjects
for (MyObj myObj : Optional.ofNullable(myObjects).orElse(Collections.emptyList())){
// do stuff with myObj
}
If you only use the list for iterations, you could just use: for (Object object : list) which wouldn't do anything for empty lists, i.e. not a single iteration.
Otherwise just check list.isEmpty().
You can create a utility class with static methods, like:
public class ListUtil {
/**
* Checks if {#link List} is null or empty.
*
* #param <E> the generic type
* #param list the list
* #return true, if is null or empty
*/
public static <E> boolean isNullOrEmpty(List<E> list) {
return list == null || list.size() == 0;
}
/**
* Checks if {#link List} is not null and empty.
*
* #param <E> the generic type
* #param list the list
* #return true, if is not null and empty
*/
public static <E> boolean isNotNullAndEmpty(List<E> list) {
return list != null && list.size() != 0;
}
}
I find it easiest to follow this convention:
If the point of my methods is to return a Collection, the method never returns null. Null is ambiguous. Instead I return Collection.emptyXXX() or ImmutableXXX.of() if using Guava.
If I have an object which is maintaining an internal list as a member, instantiate it in the constructor. I try not to do lazy instantiation unless I can prove its a significant gain because lazy code, in my opinion, tends to be more difficult to debug when issues arise.
I really see immutable or unmodifiable empty collections being a part of a contract external to objects. If you are using the collection internally, I can only really see using immutable collections if you have a good reason (concurrency, consistency, immutability of the object)