Interface for a modifiable list - java

So I have an interface:
public interface
{
List<String> getList();
}
However, I believe that the implementer can return an unmodifiable list like:
List<String> getList()
{
return Collections.unmodifiablelist(new ArrayList<String>());
}
Is there any interface, or a way to ensure than a modifiable list is always returned. I don't want to have to make a copy.

You cannot assure because the return type is Collection.What you can do is a proper doc.
In terms of API design, you should just make your javadoc clear ! People who use a method without reading its doc deserve the surprise.
Is it acceptable to return unmodifiableList or should I return array?

I think what you are looking for is not a interface but a especific implementation, because an interface defines "how thing supose to be" not "how things are". In other worlds, you are trying to establish a especific a behave, so, the best way here is to force the implementers to use a especific version of List, like this:
public interface MyInterface {
MyModifiableList getList();
}
And then, you create your version of a modifiable class that will be used by your implementers. For exemple:
public final class MyModifiableList {
// Implementation...
}

Related

Specific Collection type returned by Convenience Factory Method in Java 9

In Java 9 we have convenience factory methods to create and instantiate immutable List, Set and Map.
However, it is unclear about the specific type of the returned object.
For ex:
List list = List.of("item1", "item2", "item3");
In this case which type of list is actually returned? Is it an ArrayList or a LinkedList or some other type of List?
The API documentation just mentions this line, without explicitly mentioning that its a LinkedList:
The order of elements in the list is the same as the order of the
provided arguments, or of the elements in the provided array.
The class returned by List.of is one of the package-private static classes and therefore not part of the public API:
package java.util;
...
class ImmutableCollections {
...
// Java 9-10
static final class List0<E> extends AbstractImmutableList<E> {
...
}
static final class List1<E> extends AbstractImmutableList<E> {
...
}
static final class List2<E> extends AbstractImmutableList<E> {
...
}
static final class ListN<E> extends AbstractImmutableList<E> {
...
}
// Java 11+
static final class List12<E> extends AbstractImmutableList<E> {
...
}
static final class ListN<E> extends AbstractImmutableList<E> {
...
}
}
So this is not an ArrayList (neither a LinkedList). The only things you need to know is that it is immutable and satisfies the List interface contract.
However, it is unclear about the specific type of the returned object.
And that is all you need to know! The whole point is: these methods do return some List<Whatever> on purpose. The thing that you get back is guaranteed to fulfill the public contract denoted by the List interface. It is a list of the things given to that method, in the same order as those things were written down.
You absolutely should avoid writing any code that needs to know more about the lists returned by these methods! That is an implementation detail which should not matter to client code invoking these methods!
In that sense: your focus should be much more on the client side - for example by avoiding that raw type you are using in your example (using List without a specific generic type).
Actually the same idea is in Collectors.toList for example - you get a List back and the documentation specifically says : There are no guarantees on the type, mutability, serializability, or thread-safety of the List returned. At the moment it is an ArrayList returned, but obviously this can change at any point in time.
I wonder if the same should be done here - to explicitly mention that the type is a List and nothing more. This let's a lot of ground for future implementations to decide what type to return that would fit best - speed, space, etc.
List.of returns a List of special type like Collections.UnmodifiableList. It is neither an ArrayList nor LinkedList. It will throw an exception when you will try to modify it.
Though the question seems to have been answered by #ZhekaKozlov and #GhostCat both in terms of what the return type would be(ImmutableCollections.List) and how it has been created package private and is not a public API. Also adding to the facts that the implementation of these factory methods guarantees to fulfill the public contract denoted by the List interface.
To further provide a gist of the implementation of the ImmutableCollections then Set, Map and List a step further in it. I would add a sample representation for a List which is quite similar for Map and Set.
The ImmutableCollections currently implements these factory methods on the interface List using:
abstract static class AbstractImmutableList<E>
which extends the AbstractList class and throws an UnsupportedOperationException for all the possible operations overriding their implementation. Meaning no more operations allowed on the collection, making them equivalent to Java Immutable Collections.
Furthermore, this is extended by a class
static final class ListN<E> extends AbstractImmutableList<E>
with a constructor to evaluate certain checks for the input and its elements being NonNull to return the object consisting of an E[] elements(array of elements of type E) and overrides certain implementations as .get(int idx), .contains(Object o) based out of these elements.
The way it goes on for Map and Set is similar, just that the validations on top of the elements or a pair of key and value are ensured there. Such that you can't create these(throws IllegalArgumentException and NullPointer exceptions respectively) :
Set<String> set2 = Set.of("a", "b", "a");
Map<String,String> map = Map.of("key1","value1","key1","value1");
Set<String> set2 = Set.of("a", null);
Map<String,String> map = Map.of("key1",null);

How to subclass Guava's ImmutableList?

When I try to implement my own ImmutableList (actually a wrapper that delegates to the underlying list) I get the following compiler error:
ImmutableListWrapper is not abstract and does not override abstract method isPartialView() in com.google.common.collect.ImmutableCollection
But in fact, it seems to be impossible to override isPartialView() because it is package protected and I'd like to declare the wrapper in my own package.
Why don't I simply extend ImmutableCollection? Because I want ImmutableList.copyOf() to return my instance without making a defensive copy.
The only approach I can think of is declaring a subclass in guava's package which changes isPartialView() from package-protected to public, and then having my wrapper extend that. Is there a cleaner way?
What I am trying to do
I am attempting to fix https://github.com/google/guava/issues/2029 by creating a wrapper that would delegate to the underlying ImmutableList for all methods except spliterator(), which would it override.
I am working under the assumption that users may define variables of type ImmutableList and expect the the wrapper to be a drop-in replacement (i.e. it isn't enough to implement List, they are expecting an ImmutableList).
If you want your own immutable list but don't want to implement it, just use a ForwardingList. Also, to actually make a copy, use Iterator as parameter for the copyOf. Here's a solution that should fulfill all your requirements described in the question and your answer.
public final class MyVeryOwnImmutableList<T> extends ForwardingList<T> {
public static <T> MyVeryOwnImmutableList<T> copyOf(List<T> list) {
// Iterator forces a real copy. List or Iterable doesn't.
return new MyVeryOwnImmutableList<T>(list.iterator());
}
private final ImmutableList<T> delegate;
private MyVeryOwnImmutableList(Iterator<T> it) {
this.delegate = ImmutableList.copyOf(it);
}
#Override
protected List<T> delegate()
{
return delegate;
}
}
If you want different behavior than ImmutableList.copyOf() provides, simply define a different method, e.g.
public class MyList {
public static List<E> copyOf(Iterable<E> iter) {
if (iter instanceof MyList) {
return (List<E>)iter;
return ImmutableList.copyOf(iter);
}
}
Guava's immutable classes provide a number of guarantees and make a number of assumptions about how their implementations work. These would be violated if other authors could implement their own classes that extend Guava's immutable types. Even if you correctly implemented your class to work with these guarantees and assumptions, there's nothing stopping these implementation details from changing in a future release, at which point your code could break in strange or undetectable ways.
Please do not attempt to implement anything in Guava's Imutable* heirarchy; you're only shooting yourself in the foot.
If you have a legitimate use case, file a feature request and describe what you need, maybe it'll get incorporated. Otherwise, just write your wrappers in a different package and provide your own methods and guarantees. There's nothing forcing you, for instance, to use ImmutableList.copyOf(). If you need different behavior, just write your own method.
Upon digging further, it looks like this limitation is by design:
Quoting
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableList.html:
Note: Although this class is not final, it cannot be subclassed as it has no public or protected constructors. Thus, instances of this type are guaranteed to be immutable.
So it seems I need to create my wrapper in the guava package.

Writing class that is subclass of Vector, java

Just hoping I could get someone to tell me I am doing this right or not, as I have never written something like this before. So I have to write a class named ProcessQueue that is a subclass of Vector, as well as a constructor that will define an empty queue. Also the Vector will be holding items of type "Object." So here it is...
public class ProcessQueue<Vector>{
ProcessQueue(){}
}
Not, that's not right. That's generic, not extending.
Besides, it's not a good idea. Your ProcessQueue might have a collection of some sort underneath, but it need not extend. Prefer composition to inheritance.
If you must implement something, start by having an API that actually looks like a Queue. There's a certain behavior that's expected; make sure that yours conforms to it. The best way is to implement an interface that enforces it.
public class ProcessQueue<T> implements Queue<T> {
// Have a private collection of some sort that provides the behavior that the interface requires
}
You're not extending Vector anywhere. Change your code to:
public class ProcessQueue<T> extends Vector<T> {
}
By the way, I don't recommend you using Vector at all. Check Why is Java Vector class considered obsolete or deprecated?. IMO if you have to do this it would be better extending ArrayList.
public class ProcessQueue<T> extends ArrayList<T> {
}
And in your code use a List:
List<SomeClass> lstQueue = new ProcessQueue<SomeClass>();
U̶n̶r̶e̶l̶a̶t̶e̶d̶ ̶t̶o̶ ̶t̶h̶e̶ ̶o̶r̶i̶g̶i̶n̶a̶l̶ ̶q̶u̶e̶s̶t̶i̶o̶n̶ , I think similar as duffymo, you should not extend any of the Java Collection classes until it is a must-do. Note that there are plenty of classes to hold almost any kind of common collections, and you have Queue and PriorityQueue that can help you in your real work.
The best solution would be as pointed by duffymo, composition instead of extending a Java Collection:
public class ProcessQueue<T> {
private List<T> data = new ArrayList<T>();
//rest of code...
}
Or creating a new implementation of an interface, like Queue or List.
public class ProcessQueue<T> implements Queue<T> {
//Queue interface methods implementation...
}

If I need serializable should i use concrete List (e.g. ArrayList) or (Serializable)List?

We have a discussion in office and cannot understand which approach is better
I have a class (SomeClass) with some method which receives Serializable object. The signature is following:
public void someMethod(Serializable serializableObject){
...
}
And I need to call this method from another class, but I should provide it with some List as fact parameter. There are two different approaches
1. Serializable
private SomeClass someClass;
public void doSomething() {
List<String> al = new ArrayList<String>();
al.add("text");
someClass.someMethod((Serializable)al);
}
2. ArrayList
private SomeClass someClass;
public void doSomething() {
ArrayList<String> al = new ArrayList<String>();
al.add("text");
someClass.someMethod(al);
}
Benefit of the first example is that it adheres to the java’s best practices which says: use interface instead of concrete realization for reference type and any programmer while reading that source will understand that we don't need special behavior of the ArrayList. And the only place we need it's serializable behavior we are adding this behavior by casting it to the Serializable interface. And programmer can simply change this current realization of the List to some other serializable realization, for example, LinkedList, without any side affect on this element because we use interface List as it`s reference type.
Benefit of the second example is that we refer to ArrayList as to class which have not only List behavior but also Serializable behavior. So if someone looked at this code and tried to change ArrayList to List he would receive a compile time error which would reduce time for programmer to understand what is going on there
UPDATE: we can't change someMethod signature. It came from a third-party company and we use it not only for Serializable Lists but also for Strings, Integers and some other Serializable objects
You should use an interface when all you need is the methods an interface provides. (this is most cases) However, if you need more than one interface, you can use generics, but the simplest approach is to use the concrete type.
It's better to define ArrayList because this combines two interfaces - List + Serializable. You need both of them in one place.
It doesn't matter that much, but not that using interfaces should be applied more strictly for return types, and less strictly for local variables.
I would change the signature of the someMethod so that it reflects what it requires from the invoker of the method:
public class SomeClass {
public <T extends List<? extends Serializable> & Serializable> void someMethod(T t) {
}
public static void main(String[] args) {
SomeClass test = new SomeClass();
test.someMethod(new ArrayList<String>()); //Works
test.someMethod(new ArrayList<Image>()); //Compile time error, Image is not Serializable
List<String> l = null;
test.someMethod(l); //Compile time error
}
}
The signature of someMethod now says that you must invoke it with something that is a List, and that is Serializable, and contains elements that are Serializable
In this case, I would just use List, and not worry that the compiler cannot guarantee that your object is serializable (it most likely will be anyway, if you've done things right elsewhere).
Note that methods of the following type (which accept a Serializable parameter) provide a false sense of security, because the compiler can never guarantee that the entire object graph which needs to be serialized will actually be serializable.
public void write(Serializable s);
Consider an ArrayList (serializable) which contains non-serializable objects. The signature may as well just be:
public void write(Object o);
And then you don't have to worry about all the extraneous casting.
Also consider that, although you cannot change the signature of the API you are using, you can very easily create a wrapper API which has a different signature.
1 is generally the right thing to do. However in this case, my opinion would to be bend that and declare it as ArrayList<>. This avoids the cast and guarantees that someone can't change the implementation of the List to one that isn't Serializable.
You can't do (1) because you're not free to change the List implementation type arbitrarily, which is the whole idea of doing that. You can only use a List implementation that implements Serializable. So you may as well express that in the code.

Filter java.util.Collection in Java

I wrote a util class to filter elements in java.util.Collection as follows:
public class Util{
public static <T> void filter(Collection<T> l, Filter<T> filter) {
Iterator<T> it= l.iterator();
while(it.hasNext()) {
if(!filter.match(it.next())) {
it.remove();
}
}
}
}
public interface Filter<T> {
public boolean match(T o);
}
Questions:
Do you think it's necessary to write the method?
Any improvement about the method?
You should allow any Filter<? super T> not just Filter<T>.
Clients might also want to have a method that returns a new Collection instead:
public static <T> Collection<T> filter(Collection<T> unfiltered,
Filter<? super T> filter)
No. The guava-libraries already have this functionality. See Iterables.filter(iterableCollection, predicate) where the Predicate implements the filtering
Whether it's necessary depends on what you want to achieve. If you can use other third party libs like Google Collections, then no. If it's planned to be a one-off, then probably not. If you plan on creating different filters, then yep, looks like a good approach to keep things modular and cohesive.
One suggestion - you might want to return a Collection - that way, you have the option of returning a new filtered Collection rather than mutating the original Collection. That could be handy if you need to use it in a concurrent context.
You might also look at the responses to this similar question.
Regarding question 1 there are already a lot of collection libraries. Filtering is offered by instance by apache common-collections CollectionUtils and google collections Iterables .
Looks nice - but we can't decide, if it's 'necessary' to write it (OK, you actually wrote it ;) )
The remove() method is not always implemented, it is labelled (optional). Some Iterators just throw an UnsupportedOperationException. You should catch it or convert it to a custom exception saying, that this collection can't be filtered.
And then you could change the method signature to
public static <T> void filter(Iterable<T> i, Filter<T> filter)
because iterators are not limited to Collections. With this utility method you could filter every 'container' that provides an iterator which allows remove operations.
Do you think it's necessary to write the method?
If you don't mind using a third party library then no.
Some suggestions for third party libraries that provide this functionality:
You might want to look at Functional Java which provides filter plus many other higher order functions found in true-blue functional languages.
Example:
List<Person> adults = filter(people, new F1<Person, Boolean>() {
public Boolean f(Person p) {
return p.getAge() > 18;
}
});
Another alternative is using lambdaj - a library with similar goals but is much more concise than Functional Java. lambdaj doesn't cover as much ground as Functional Java though.
Example:
List<Person> adults = filter(having(on(Person.class).getAge(), greaterThan(18)), people);
I think it would be cool to have a visit(T o) method defined in your Filter<T> interface. That way the filter implementation can decide what action to take on the visited object when there is a match.

Categories

Resources