I had two classes: ParentClass and SubClass. SubClass inherit from ParentClass.
I had the following code: (inside class)
List<SubClass> lstSub;
//some initialization
public ListIterator getLstIterator(int i) {
return lstSub.listIterator(i);
}
And client class uses it the following way:
ListIterator<ParentClass> lstParent = getLstIterator(0); //assign ListIterators
So, the question:
What does the program do while assigning ListIterators:
1) it creates a new list and copies there elements from source list, casting them to ParentClass;
2) it simply creates a link to lstSub and from this time this list is interpreted as List for ListIterator?
Or it does something else?
I'm interested in it because of program performance. I'm new to Java and appreciate any help.
It doesn't create another list. If you get a list iterator without knowing the class in the list, that's going to be an error in your generics usage. You should get a warning when you do that assignment, but it's just a warning. When you actually use it it'll cast to whatever class. Properly you'd hold on to that as ListIterator<? extends ParentClass> if you wanted a list iterator, but actually holding on to an iterator is a little weird.
Finally, just a bit of advice, I'd not worry about performance of the language features too much, especially if you're just getting your feet in the language.
A new instance of ListIterator is created. The reference to the new object is copied into lstParent
See here
public ListIterator<E> listIterator(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index);
}
Disclaimer: This example is specific to ArrayList.
Performance-wise, there's no list copying going on.
But to have the compiler check the type-safety of the code, you should declare the type parameters like this:
public ListIterator<SubClass> getLstIterator(int i) {
return lstSub.listIterator(i);
}
...
ListIterator<? extends ParentClass> lstParent = getLstIterator(0);
Related
I have a method which returns an Iterator<IFoo>. Inside that method, if I try to return someArrayList of type ArrayList<Foo>, I get a compilation error saying:
Type mismatch: cannot convert from Iterator<Foo> to Iterator<IFoo>
Here's the type Hierarchy:
Interface:IFoo
--Class: Foo (Implements IFoo)
And, here's my method:
public Iterator<IFoo> iterator() {
return someArrayList.iterator();
}
My question is, when the method wants me to return something of type Iterator<IFoo>, why can't we return someArrayList of type ArrayList<Foo> since Foo implements IFoo?
Update at 8:38 AM on Friday, June 20, 2014 (UTC)
The method in question public Iterator<IFoo> iterator() cannot be modified since I'm implementing an interface.
I should have mentioned this before. Sorry.
Going off your most recent edit, where you say you can't modify the method signature (which is really too bad, because a more flexible signature would have avoided this...):
One solution is to create a new List with the proper type and use the iterator from that. This works because the various constructors for lists are far more flexible in the types they accept and will take subtypes. The main disadvantage is that this will produce a shallow copy of your original ArrayList, which takes up extra space (albeit not too much unless you're working with very large lists). This is basically your posted answer in a much more compact form.
public Iterator<IFoo> iterator() {
return new ArrayList<IFoo>(someArrayList).iterator();
}
You have to specify the type arguments explicitly here because otherwise the type will be inferred to be Foo, which just leaves you back where you were.
Alternatively, if the extra space required by the new ArrayList() call isn't appealing, you can write an anonymous subclass of Iterator that simply acts as a wrapper (I think I got the syntax right; might have made a minor mistake or two, but those should be easy to fix). It's more writing, but it's leaner on memory usage, which might be desirable:
public Iterator<IFoo> iterator() {
return new Iterator<IFoo>() {
private final Iterator<? extends IFoo> iterator = someArrayList.iterator();
#Override
public boolean hasNext() {
return iterator.hasNext();
}
#Override
public Number next() {
return iterator.next();
}
#Override
public void remove() {
iterator.remove();
}
};
}
One important thing to note is that these solutions are not exactly equivalent.
Your solution and my first solution return iterators that operate on a different list than your original one. This distinct list is a shallow copy, so you'll get the same results from hasNext() and next(). However, if you call remove(), your original list will remain unaffected, and only the copy will be changed.
The anonymous subclass will perform all its operations on your original list, as if your original solution had worked in the first place.
Generics doesnt work that way, you would need to use wildcards for it and/or boundaries.
public Iterator<? extends IFoo> iterator()
It's basicly because Java generics are invariant. To make it possible to return generic subtypes, type-system should allow covariance. Without defining upper-bound of type, this won't work. Like pointed in earlier posts, this can be achieved by relaxing your type definition to allow subtypes returned:
public Iterator<? extends IFoo> iterator()
There is a good article about covariance and contravariance in Java, which also explains why this check has to be done at compile time.
So this is what I (the poster of this question) did, given the constraint that I cannot modify the method public Iterator<IFoo> iterator():
Note: certain variables (e.g. someArrayList) relate to the question.
public Iterator<IFoo> iterator() {
Iterator<Foo> fooIterator = someArrayList.iterator();
ArrayList<IFoo> iFooList = new ArrayList<IFoo>();
while (fooIterator.hasNext()) {
IFoo iFoo = (IFoo) fooIterator.next();
iFooList.add(iFoo);
}
return iFooList.iterator();
}
Please point out if this is a wrong way.
Example code:
modifyMyList(myList);
public void modifyMyList(List someList){
someList.add(someObject);
}
or:
List myList = modifyMyList(myList);
public List modifyMyList(List someList){
someList.add(someObject)
return someList;
}
There is also a 3rd option I believe: You can create a new List in modifyMyList method and return this new List...
( 3rd option is here, I was too lazy but someone already added it in the answers: )
List myList = modifyMyList(myList);
public List modifyMyList(List someList){
List returnList = new ArrayList();
returnList.addAll(someList);
returnList.add(someObject);
return Collections.unmodifiableList(returnList);
}
Is there any reason why I should choose one over another? What should be considered in such case?
I have a (self imposed) rule which is "Never mutate a method parameter in a public method". So, in a private method, it's ok to mutate a parameter (I even try to avoid this case too). But when calling a public method, the parameters should never be mutated and should be considered immutable.
I think that mutating method arguments is a bit hacky and can lead to bugs that are harder to see.
I have been known to make exceptions to this rule but I need a really good reason.
Actually there is no functional difference.
You'll come to know the difference when you want the returned list
List someNewList = someInstnace.modifyMyList(list);
The second is probably confusing as it implies a new value is being created and returned - and it isn't.
An exception would be if the method was part of a 'fluent' API, where the method was an instance method and was modifying its instance, and then returning the instance to allow method chaining: the Java StringBuilder class is an example of this.
In general, however, I wouldn't use either.
I'd go for your third option: I write a method that creates and returns a new list with the appropriate change. This is a bit artificial in the case of your example, as the example is really just reproducing List.add(), but...
/** Creates a copy of the list, with val appended. */
public static <T> List<T> modifyMyList(List<T> list, T val) {
List<T> xs = new ArrayList<T>(list);
xs.add(val);
return xs;
}
Aside: I wouldn't, as suggested by Saket return an immutable list. His argument for immutability and parallelism is valid. But most of the time Java programmers expect to be able to modify a collection, except in special circumstances. By making you method return an immutable collection, you limit it's reusability to such circumstances. (The caller can always make the list immutable if they want to: they know the returned value is a copy and won't be touched by anything else.) Put another way: Java is not Clojure. Also, if parallelism is a concern, look at Java 8 and streams (the new kind - not I/O streams).
Here's a different example:
/** Returns a copy of a list sans-nulls. */
public static <T> List<T> compact(Iterable<T> it) {
List<T> xs = new ArrayList<T>();
for(T x : it)
if(x!=null) xs.add(x);
return xs;
}
Note that I've genercized the method and made it more widely applicable to taking an Iterable instead of a list. In real code, I'd have two overloaded versions, one taking an Iterable and one an Iterator. (The first would be implemented by calling the second, with the iterable's iterator.) Also, I've made it static as there was no reason for your method to be an instance method (it does not depend on state from the instance).
Sometimes, though, if I'm writing library code, and if it is not clear whether a mutating or non-mutating implementation is more generally useful, I create both. Here's a fuller example:
/** Returns a copy of the elements from an Iterable, as a List, sans-nulls. */
public static <T> List<T> compact(Iterable<T> it) {
return compact(it.iterator());
}
public static <T> List<T> compact(Iterator<T> iter) {
List<T> xs = new ArrayList<T>();
while(iter.hasNext()) {
T x = iter.next();
if(x!=null) xs.add(x);
}
return xs;
}
/** In-place, mutating version of compact(). */
public static <T> void compactIn(Iterable<T> it) {
// Note: for a 'fluent' version of this API, have this return 'it'.
compactIn(it.iterator());
}
public static <T> void compactIn(Iterator<T> iter) {
while(iter.hasNext()) {
T x = iter.next();
if(x==null) iter.remove();
}
}
If this was in a real API I'd check the arguments for null and throw IllegalArgumentException. (NOT NullPointerException - though it is often used for this purpose. NullPointerException happens for other reasons as well, e.g. buggy code. IllegalArgumentException is better for invalid parameters.)
(There'd also be more Javadoc than actual code too!)
The first and second solution are very similar, The advantage of the second is to permit chaining. The question of "is it a good practise" is subjected to debate as we can see here:
Method Chaining in Java
So the real question is between the first solution with mutable list and the third with a unmutable list, and again, there is not a unique response, it is the same debate between returning String, which are immutable and using Stringbuffer, which are mutable but permits better performance.
If you need reliablility of your API , and if you don't have performance issues use immutable (the third solution). Use it if your lists are always small.
If you need only performance use a mutable list (the first solution)
I will recommend creating a new list in the method and returning an immutable list. That way your code will work even when you are passed in an Immutable list. It is generally a good practice to create immutable objects as we generally move towards functional programming and try to scale across multiple processor architectures.
List myList = modifyMyList(myList);
public List modifyMyList(List someList){
List returnList = new ArrayList();
returnList.addAll(someList);
returnList.add(someObject);
return Collections.unmodifiableList(returnList);
}
As I said in my other answer, I don't think you should mutate the list parameter. But there are times where you also don't want to take a copy of the original list and mutate the copy.
The original list might be large so the copy is expensive
You want the copy to be kept up-to-date with any updates to the original list.
In these scenarios, you could create a MergedList which is a view over two (or perhaps more) lists
import java.util.*;
public class MergedList<T> extends AbstractList<T> {
private final List<T> list1;
private final List<T> list2;
public MergedList(List<T> list1, List<T> list2) {
this.list1 = list1;
this.list2 = list2;
}
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
Iterator<T> it1 = list1.iterator();
Iterator<T> it2 = list1.iterator();
#Override
public boolean hasNext() {
return it1.hasNext() || it2.hasNext();
}
#Override
public T next() {
return it1.hasNext() ? it1.next() : it2.next();
}
};
}
#Override
public T get(int index) {
int size1 = list1.size();
return index < size1 ? list1.get(index) : list2.get(index - size1);
}
#Override
public int size() {
return list1.size() + list2.size();
}
}
The you could do
public List<String> modifyMyList(List<String> someList){
return new MergedList(someList, List.of("foo", "bar", "baz"));
}
Both ways will work because in this case java works with the reference of the List but i prefer the secound way because this solution works for pass by value too, not only for pass by reference.
Functionally both are same.
However when you expose your method as an API, second method may give an impression that it returns a new modified list other than the original passed list.
While the first method would make it clear (of-course based on method naming convention) that it will modify the original list (Same object).
Also, the second method returns a list, so ideally the caller should check for a null return value even if the passed list is non null (The method can potentially return a null instead of modified list).
Considering this I generally prefer to use method one over second.
Hi guys i got a problem with an unsafe cast operation.
Here is the problem. I gotta Constructor which accepts different types of Orders (PlayList, UserOperations, etc.) or should. So i decided to give it a Parameter as Object and check the type of the received once called. The Problem is one of those is a parameterized ArrayList (ArrayList < PlayList >) and since it is impossible to check a parameterized ArrayList I have to "dig" in. At first step i check if it is an ArrayList, at second I go into it an check the type of its content.
The problem afterwards is I get an unsafe cast warning which i dunno yet how to handle.
Greetings
public Order(int aTyp, Object aOrderContent) {
this.orderTyp = aTyp;
if (aOrderContent instanceof ArrayList< ? >) {
ArrayList<?> objList = (ArrayList< ? >)aOrderContent;
if (objList.get(0) != null && (objList.get(0)) instanceof PlayList) {
playList.addAll((ArrayList<PlayList>)aOrderContent) ;
}
} else if (aOrderContent instanceof UserOP) {
}
}
Rethink your design. Don't make the constructor take an Object. This is too opaque and allows consumers of your code to pass any type. It sounds like you should be using a generic class instead (though it's hard to tell based on your partial example). Possible solution:
// Might need an upper bound on T if you want to limit the allowed parameterizations
class Order<T> {
private final int orderTyp;
private final List<T> someList = new ArrayList<>();
public Order(int aTyp, List<t> aOrderContent) {
this.orderTyp = aTyp;
someList.addAll(aOrderContent);
}
}
Keep in mind it may be better to use an enum instead of int for the orderTyp, if you know (at compile time) all the possible type values.
Side note: if a List is empty, List#get(0) with throw an exception, not return null.
Instead of making the constructor take an Object overload you constructor. Have one take an List<?> and one take a UserOP ect. Also, it would be ideal if all the options for the List extended from the same interface so you could have List<MyInterface> instead of List<?>
I tried to cast an Iterator of a class to an iterator of a subclass of said class. This gave me an "inconvertible types" error. Why is this not possible and what is the most elegant way to work around it? (Or alternatively, why is it a bad idea if it is?)
Using a for-each loop is not a solution in this case: I'm trying to implement iterator() and the easiest way to do this would be to return the iterator() of one of my class' fields, but that one doesn't have the exact required type. I can't change the signature of my iterator()either.
public interface SomeoneElsesInterface {
public Iterator<SomeoneElsesInterface> iterator();
}
public abstract class MyAbstractClass implements SomeoneElsesInterface {
final MyAbstractClass[] things;
public MyAbstractClass(SomeoneElsesInterface... things) {
this.things = (MyAbstractClass[]) things;
}
}
public class MyClass extends MyAbstractClass {
public MyClass(MyAbstractClass thing1, MyAbstractClass thing2) {
super(thing1, thing2);
}
public Iterator<SomeoneElsesInterface>() {
return (Iterator<SomeoneElsesInterface>) Arrays.asList(things).iterator();
}
}
I could, of course, just change the type of things. However, I would need a lot of casts in other places in that case. I do know that my constructor won't be called with objects that are not MyAbstractClasss but I cannot change the interface anyway.
This looks to be as simple as using explicit type argument specification:
public class MyClass extends MyAbstractClass {
// ...
public Iterator<SomeoneElsesInterface> iterator() {
return Arrays.<SomeoneElsesInterface>asList(things).iterator();
}
}
The problem is that Arrays#asList() is inferring that you want a list of type List<MyAbstractClass>, which will yield an iterator of type Iterator<MyAbstractClass>. Since Iterator's type parameter is not covariant, you cannot supply an Iterator<MyAbstractClass> where an Iterator<SomeoneElsesInterface> is required. By forcing Arrays#asList() to create a list of type List<SomeoneElsesInterface>, as shown above, you also wind up with the intended iterator type coming back from your call to Iterable#iterator().
The author of SomeoneElsesInterface would have been kinder to specify the return type of its iterator() method as Iterator<? extends SomeoneElsesInterface>.
I think from your question you're trying to do something like this:
Iterator<Object> original = ...
Iterator<String> converted = (Iterator<String>)original;
Is that correct?
If so, that is, unfortunately, impossible. The problem is that original can contain objects that are not Strings, so allowing that cast would break the generics contract, i.e. converted could contain something that is not a String.
I don't think there is an elegant workaround for this.
You say the easiest way to implement iterator() is to return an instance field's iterator, so I'm guessing you have something like this:
class IterableThing implements Iterable<Foo> {
private Collection<Bar> someStuff;
public Iterator<Foo> iterator() {
return (Iterator<Foo>)someStuff.iterator();
}
}
class Bar {
}
class Foo extends Bar {
}
If someStuff can be guaranteed to contain only instances of Foo, then can you declare someStuff to be a Collection<Foo> rather than a Collection<Bar>? If not, then it doesn't really make sense to just return someStuff's iterator because it might contain something that is not a Foo.
I guess you need to think about what guarantees you can actually make. If you can't guarantee that someStuff only contains Foos then you will probably have to maintain your own state, or filter the contents of someStuff on demand.
EDIT: You've updated your question with code. Awesome.
So it looks like you're actually trying to return an iterator over the superclass of the type. That makes things a lot easier.
In your particular case, you can probably solve it with this:
return Arrays.<SomeoneElsesInterface>asList(things).iterator();
It'll generate some warnings, but that's OK because you know that you've guaranteed type safety.
Use for-each loop instead of Iterator.
for-each was introduced from Java 1.5
See this link for further details:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html
What if you change Arrays.asList(things) to Arrays.asList((SomeoneElsesInterface[]) things)? Once the array is cast to the right type the List and Iterator should follow.
Example of Java for-each (complementing Kumar answer):
List<String> strings = new ArrayList<String>();
strings.add( "one" );
strings.add( "two" );
strings.add( "three" );
for ( String item : strings ) {
System.out.println( item );
}
How do I write a static method in Java that will take a List, perform an action on each element, and return the result (without affecting the original of course)?
For example, if I want to add 2 to each element what goes in the ... here? The concrete return type must be the same, e.g. if my List is a LinkedList with values 1,2,3 I should get back a LinkedList with values 3,4,5. Similarly for ArrayList, Vector, Stack etc, which are all Lists.
I can see how to do this using multiple if (lst instanceof LinkedList) ... etc... any better way?
import java.util.List;
public class ListAdd {
static List<Integer> add2 (List<Integer> lst) {
...
return result;
}
}
There are already many answers, but I'd like to show you a different way to think of this problem.
The operation you want to perform is known as map in the world of functional programming. It is something we do really all the time in functional languages.
Let M<A> be some kind of container (in your case, M would be List, and A would be Integer; however, the container can be lots of other things). Suppose you have a function that transforms As into Bs, that is, f: A -> B. Let's write this function as of type F<A, B>, to use a notation closer to Java. Note that you can have A = B, as in the example you give (in which A = B = Integer).
Then, the operation map is defined as follows:
M<B> map(M<A>, F<A, B>)
That is, the operation will return a M<B>, presumably by applying F<A, B> to each A in M<A>.
In practice...
There's a brilliant library developed by Google, called Guava, which brings lot's of functional idioms to Java.
In Guava, the map operation is called transform, and it can operate on any Iterable. It has also more specific implementations that work directly on lists, sets, etc.
Using Guava, the code you want to write would look like this:
static List<Integer> add2(List<Integer> ns) {
return Lists.transform(ns, new Function<Integer, Integer>() {
#Override Integer apply(Integer n) { return n + 2; }
}
}
Simple as that.
This code won't touch the original list, it will simply provide a new list that calculates its values as needed (that is, the values of the newly created list won't be calculated unless needed -- it's called a lazy operation).
As a final consideration, it is not possible for you to be absolutely sure that you will be able to return exactly the same implementation of List. And as many others pointed out, unless there's a very specific reason for this, you shouldn't really care. That's why List is an interface, you don't care about the implementation.
Fundamentally, the List interface doesn't make any guarantees that you'll have a way to duplicate it.
You may have some luck with various techniques:
Using clone() on the passed in List, although it may throw, or (since it is protected in Object) simply not be accessible
Use reflection to look for a public no-argument constructor on the passed-in List
Try to serialize and deserialize it in order to perform a "deep clone"
Create some sort of factory and build in knowledge of how to duplicate each different kind of List your code may encounter (What if it's a wrapper created by unmodifiableList(), or some oddball custom implementation backed by a RandomAccessFile?)
If all else fails, either throw, or return an ArrayList or a Vector for lack of better options
You could use reflection to look for a public zero-arg constructor on the result of lst.getClass() and then invoke() it to obtain the List into which you'll place your results. The Java Collections Framework recommends that any derivative of Collection offer a zero-arg constructor. That way, your results we be of the same runtime class as the argument.
Here is a variant which does neither copies nor modifies the original list. Instead, it wraps the original list by another object.
public List<Integer> add2(final List<Integer> lst) {
return new AbstractList<Integer>() {
public int size() {
return lst.size();
}
public Integer get(int index) {
return 2 + lst.get(index);
}
};
}
The returned list is not modifiable, but will change whenever the original list changes.
(This implements the iterator based on index access, thus it will be slow for a linked list. Then better implement it based on AbstractSequentialList.)
Of course, the resulting list will obviously not be of the same class as the original list.
Use this solution only if you really only need a read-only two added view of your original list, not if you want a modified copy with similar properties.
The whole point of using an interface, in this case List, is to abstract the fact that the implementation is hidden behind the interface.
Your intention is clear to me, however: the Clonable interface supports creating a new instance with the same state. This interface might not be defined on your List.
Often it's a good idea to rethink this situation: why do you need to clone the List in this place, this class? Shouldn't your list-creator be responsible for cloning the list? Or shouldn't the caller, who knows the type, make sure he passes in a clone of his list?
Probably, if you look for the semantics as you defined it, you can implement all your supported Lists:
static Vector<Integer> addTwo(Vector<Integer> vector) {
Vector<Integer> copy = null; // TODO: copy the vector
return addTwo_mutable(copy);
}
static ArrayList<Integer> addTwo(ArrayList<Integer> aList) {
ArrayList<Integer> copy = null; // TODO: copy the array list
return addTwo_mutable(copy);
}
static LinkedList<Integer> addTwo(LinkedList<Integer> lList) {
LinkedList<Integer> copy = null; // TODO: copy the linked list
return addTwo_mutable(copy);
}
private <T extends List<Integer>> static T addTwo_mutable(T list) {
return list; // TODO: implement
}
Even, when you don't support a data-type, you'll get a nice compiler error that the specified method does not exists.
(code not tested)
Just to show you that what you want to do is not possible in the general case, consider the following class:
final class MyList extends ArrayList<Integer> {
private MyList() {
super.add(1);
super.add(2);
super.add(3);
}
private static class SingletonHolder {
private static final MyList instance = new MyList();
}
public static MyList getInstance() {
return SingletonHolder.instance;
}
}
It is a singleton (also, a lazy, thread-safe singleton by the way), it's only instance can be obtained from MyList.getInstance(). You cannot use reflection reliably (because the constructor is private; for you to use reflection, you'd have to rely on proprietary, non-standard, non-portable APIs, or on code that could break due to a SecurityManager). So, there's no way for you to return a new instance of this list, with different values.
It's final as well, so that you cannot return a child of it.
Also, it would be possible to override every method of ArrayList that would modify the list, so that it would be really an immutable singleton.
Now, why would you want to return the exact same implementation of List?
OK well someone mentioned reflection. It seems to be an elegant solution:
import java.util.*;
public class ListAdd {
static List<Integer> add2 (List<Integer> lst) throws Exception {
List<Integer> result = lst.getClass().newInstance();
for (Integer i : lst) result.add(i + 2);
return result;
}
}
Concise, but it thows an checked exception, which is not nice.
Also, wouldn't it be nicer if we could use the method on concrete types as well, e.g. if a is an ArrayList with values 1, 2, 3, we could call add2(a) and get an ArrayList back? So in an improved version, we could make the signature generic:
static <T extends List<Integer>> T add2 (T lst) {
T res;
try {
res = (T) lst.getClass().newInstance();
} catch (InstantiationException e) {
throw new IllegalArgumentException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
for (Integer i : lst) res.add(i + 2);
return res;
}
I think throwing a runtime exception is the least worst option if a list without a nullary construcor is passed in. I don't see a way to ensure that it does. (Java 8 type annotations to the rescue maybe?) Returning null would be kind of useless.
The downside of using this signature is that we can't return an ArrayList etc as the default, as we could have done as an alternative to throwing an exception, since the return type is guaranteed to be the same type as that passed in. However, if the user actually wants an ArrayList (or some other default type) back, he can make an ArrayList copy and use the method on that.
If anyone with API design experience reads this, I would be interested to know your thoughts on which is the preferable option: 1) returning a List that needs to be explicity cast back into the original type, but enabling a return of a different concrete type, or 2) ensuring the return type is the same (using generics), but risking exceptions if (for example) a singleton object without a nullary constructor is passed in?