I am implementing a simple LinkedList class and I want it to use generics. The class declaration is:
public class LinkedList<E> extends AbstractList<E> implements List<E> {
This is a teaching example, so the Abstract parent and the interface are also my own. The problem arises when I realized that to add and maintain sorting, I need a class (E) which is also Comparable. I thought I could limit that to just the methods where it actually makes a difference. But based on the comments below, that may be my basic misunderstanding.
Here's the code:
public void addSorted(<E extends Comparable<E>> value) {
if (front == null || value.compareTo(front.word) <= 0) {
// insert at front of list
front = new ListNode<E>(value, front);
} else {
// insert in middle of list
ListNode<E> current = front;
while (current.next != null && current.next.word.compareTo(value) < 0) {
current = current.next;
}
current.next = new ListNode<E>(value, current.next);
}
}
It seemed to me that if I never want to call addSorted then why should the particular class be limited to E's that implement Comparable? Or is there a totally different way to do it, with a generic analog to instances?
Consider what happens if you are able to call both add and addSorted on a LinkedList instance:
LinkedList<String> list = new LinkedList<>();
list.add("c"); list.add("a");
list.addSorted("b");
In this case, where do you expect "b" to be inserted into a list ["c", "a"]:
It is lexicographically before "c", so it could be inserted at the start, yielding ["b", "c", "a"];
It is lexicographically after "a", so it could be inserted at the end, yielding ["c", "a", "b"];
But neither list is really "sorted" afterwards.
To me, the only obvious way to resolve this ambiguity is to force all adds to be done in a sorted way. This implies that you should create a subclass of LinkedList, SortedLinkedList, which overrides the LinkedList.add method:
class SortedLinkedList<E extends Comparable<E>> extends LinkedList<E> {
void add(E element) {
// The implementation of addSorted.
}
}
In general, the way I would handle methods that should only available for certain generic types is to do it using a method which accepts an instance of the class as the first parameter, outside the definition of the class (or inside the definition of the class, but defined as static). This means that it's not part of the interface of the class, so it's not present for classes with incompatible generic types.
For example, if you wanted to add a sort method to sort LinkedLists, this is obviously only sensible for ones with Comparable elements:
static <E extends Comparable<E>> void sort(LinkedList<E> list) {
// ...
}
For example:
LinkedList<String> strList = new LinkedList<>();
// ... Add elements.
sort(strList); // OK.
LinkedList<Object> objList = new LinkedList<>();
// ... Add elements.
sort(objList); // Compiler error - Object is not a valid bound.
Related
I want to create an iterator class which allows me to iterate through lists with generic types (e.g. lst1 integer, lst2 string) one item after another.
For this I have to consider the following given situation.
The interface is a generic Iterator. This part of the code cannot be modified.
interface Iterator<E> {
E next ();
boolean hasNext();
}
The list class is also defined as following. The most important, a list object can return a iterator object with the method getIterator(). This part of the code cannot be modified.
class List<T> {
class ListNode {
T val;
ListNode next;
ListNode (T v) {
val = v; next = null;
}
}
ListNode head;
List (ListNode hd) { head = hd; }
List () { this(null); }
void prepend (T val) {
ListNode p = new ListNode(val);
p.next = head;
head = p;
}
//some other methods
class ListIterator implements Iterator<T> {
ListNode pos;
ListIterator () {
pos = head;
}
public T next () {
T res = pos.val;
pos = pos.next;
return res;
}
public boolean hasNext () {
return pos != null;
}
}
Iterator<T> getIterator () {
return this.new ListIterator();
}
}
Lets assume both list have the same type and for now they have also the same length. I tried to create a class with two iterator objects and used the methods of the iterator objects to implement the interface Iterator. This part of the code is created by me and can be modified.
class ZipIterator<T> implements Iterator<T>
{
int counter;
Iterator<T> first;
Iterator<T> second;
ZipIterator (Iterator<T> f, Iterator<T> s)
{
first = f;
second = s;
counter = 0;
}
public T next ()
{
if (counter % 2 == 0)
{
counter++;
return first.next();
}
else
{
counter++;
return second.next();
}
}
public boolean hasNext ()
{
if (counter % 2 == 0)
return first.hasNext();
else
return second.hasNext();
}
}
This works fine for two list with the same type. Here is the code and the output I used for the test:
class IteratorUtils
{
public static void main (String[] args)
{
List<Integer> lst1 = new List<>();
List<Integer> lst2 = new List<>();
lst1.prepend(3);
lst1.prepend(2);
lst1.prepend(1);
lst2.prepend(8);
lst2.prepend(9);
lst2.prepend(10);
Iterator<Integer> it1 = lst1.getIterator();
Iterator<Integer> it2 = lst2.getIterator();
ZipIterator<Integer> zit = new ZipIterator<>(it1, it2);
while (zit.hasNext())
{
System.out.println(zit.next());
}
}
}
Output:
1
10
2
9
3
8
Now I want to implement the ZipIterator in a generic way, so I can use two lists with different types of items (e.g. integer and string). I know I have to change the class ZipIterator so the method next() returns a generic type but I don't know how.
This is a university task i have to do and the prof has left a hint "use wild cards like: ? extends T, ? super T, ? extends Object". But with the wild cards i can only specify the types in or against the inherits direction, right? Is this possible to change the ZipIterator class that way so it accepts two iterator objects with different types?
I won't give the full solution (and judging by your effort you don't want it), but I will attempt to explain in a way that will let you find it yourself.
First of all an unrelated note: you're specifying a specific iteration order. I assume this is fine and I will not touch it.
Your professor gave you the hint of using bounded generics. Let's understand why they are needed (see also the tutorial here and/or here). If you were asked to write a single method that takes an argument of any of 2 unknown types, your solution would be to find and take their common superclass - Object.
In generics the situation is similar - find the most common denominator, only the syntax is a bit more tricky. If you were to write the constructor
ZipIterator(Iterator<Object> f, Iterator<Object> s) {...}
and attempt the initialization
List<Integer> lst1 = new List<>();
List<String> lst2 = new List<>();
new ZipIterator(it1, it2);
you would get a compilation error (read it). That is because a List<String> is not a List<Object>, even though a String is an Object. The correct way to do this is
ZipIterator(Iterator<? extends Object> f, Iterator<? extends Object> s) {...}
where ? extends Object means "any type that extends Object" (which is all of them because Object...).
So you have the constructor, and you would need to make changes to your class in order to accommodate it. You don't even need to implement the given Iterator<E>, you just hold 2 of those like you already do. Lastly, the class itself need not have a generic type: since its next method must be able to return any type, it always returns Object.
If you have any questions during your future attempts at this problem, or you find that this solution doesn't fit the assignment's requirements, feel free to post a comment.
I know I have to change the class ZipIterator so the method next() returns a generic type but I don't know how.
That's not quite right. Since ZipIterator<T> extends Iterator<T>, it's actually set in stone that its next() method must return T. And this makes sense: the whole point of the iterator's type parameter is to let you specify the type that its next() method will return.
Instead, all your professor wants is for it to be possible to construct a ZipIterator<...> from two iterators with different type arguments. For example, (s)he wants to be able to write:
List<Integer> listOfIntegers = ...;
List<String> listOfStrings = ...;
ZipIterator<Object> zipIterator =
new ZipIterator<>(listOfIntegers.getIterator(), listOfStrings.getIterator());
Note that, since zipIterator.next() will sometimes return an Integer and sometimes a String, we had to go with something like ZipIterator<Object> that allows for both possibilities. Other options included ZipIterator<Serializable> or ZipIterator<Comparable<?>>, since Integer-s and String-s are both Serializable and both Comparable<?>.
So the problem that your professor wants you to solve is that in your current code, your constructor requires both iterators to have the exact same type argument (as each other, and as the ZipIterator itself):
ZipIterator (Iterator<T> f, Iterator<T> s)
Do you see how to fix that?
as i understand you want to iterate over list of different types one of solution is to make your constructor accepted iterator fulfill the requirement that it being iterator of any thing that extends object but this will limits your use of the retrieved items to just use it as objects or you will have to cast them to achieve further tasks a less restrictive approach is to make the constructor accepted iterator fulfill the requirement that it being iterator of any thing that extends the nearest common ancestor like this ZipIterator(Iterator<? extends T> f, Iterator<? extends T> s) so your class will look like this
class ZipIterator<T> implements Iterator<T> {
int counter;
Iterator<? extends T> first;
Iterator<? extends T> second;
ZipIterator(Iterator<? extends T> f, Iterator<? extends T> s) {
first = f;
second = s;
counter = 0;
}
#Override
public T next() {
if (counter % 2 == 0) {
counter++;
return first.next();
} else {
counter++;
return second.next();
}
}
#Override
public boolean hasNext() {
if (counter % 2 == 0) {
return first.hasNext();
} else {
return second.hasNext();
}
}
}
then to use it you can specify the best appropriate super class that both types converge to it, in cases of it is Object you can write ZipIterator<Object> zit = ,the following code will show you an arbitrary use case
List<StringBuilder> bl= Arrays.asList(new StringBuilder("hi i'm builder"));
List<String> sl = Arrays.asList("hi i'm string");
ZipIterator<CharSequence> zit = new ZipIterator<>(bl.iterator(), sl.iterator());
while (zit.hasNext()) {
CharSequence cs = zit.next();
System.out.println(cs.subSequence(6,cs.length()));
}
Thanks for the help. I have learned a lot. Here comes my solution and some more explanations to the task.
Please notice first, that the design of the ZipIterator class is not set in stone. ZipIterator was designed by me. There may be another solution but this was my attempt.
To specify the task: "Please construct a class IteratorUtils with several methods. The method zip receives two iterator objects and returns one iterator object, which iterates alternating through the items of the two received iterator objects. The iterator returned by the zip function should stop after the last item of the shorter iterator object. Use wildcards so you can apply the zip function to diffrent types of iterator objects."
For this I first created the class IteratorUtils. Please notice that the design of the zip function is also not set in stone. In the task it only says: "The method zip receives two iterator objects and returns one iterator object, which iterates alternating through the items of the two received iterator objects."
class IteratorUtils
{
static ZipIterator zip (Iterator<? extends Object> first, Iterator<? extends Object> second)
{
return new ZipIterator(first, second);
}
}
Then I created the class ZipIterator. After reading through your answers and some tutorials I understood the meaning of bounded type parameters in this task. Like user1803551 said, the ZipIterator class should not be generic. I just had to realize that I hat to find the common superclass (here Object). So I had to change my ZipIterator class to the following:
class ZipIterator
{
int counter;
Iterator first;
Iterator second;
ZipIterator (Iterator<? extends Object> f, Iterator<? extends Object> s)
{
first = f;
second = s;
counter = 0;
}
public Object next ()
{
if (counter % 2 == 0)
{
counter++;
return first.next();
}
else
{
counter++;
return second.next();
}
}
public boolean hasNext ()
{
if (counter % 2 == 0)
return first.hasNext();
else
return second.hasNext();
}
}
In my main method I use the following code:
public static void main (String[] args)
{
List<Integer> lst1 = new List<>();
List<String> lst2 = new List<>();
lst1.prepend(3);
lst1.prepend(2);
lst1.prepend(1);
lst2.prepend("three");
lst2.prepend("two");
lst2.prepend("one");
Iterator<Integer> it1 = lst1.getIterator();
Iterator<String> it2 = lst2.getIterator();
ZipIterator zit = zip(it1, it2);
while (zit.hasNext())
{
System.out.println(zit.next());
}
}
Output:
1
one
2
two
3
three
I'm very new to java and my first question is what is this Comparable thing? and in my sample code, why Class Bag<T extends Comparable<T>>?? What's the purpose?
My second question is how to remove an item from this Comparable array. I have wrote the removeMin method, I have found the item, I named the variable "min", how do I go on and remove this min item from the arrayList? Thanks a lot!
Here's some partial code:
public class Bag<T extends Comparable<T>> implements Iterable<T> {
private int MAX_ITEMS = 10; // initial array size
private int size;
private Comparable[] data;
public Bag( ) {
//data = (Comparable []) new Object[MAX_ITEMS];
data = (T []) new Comparable[MAX_ITEMS];
size = 0;
}
public Comparable removeMin(){
Iterator<T> iterator=iterator();
T min = iterator.next();
while (iterator.hasNext())
{
T next = iterator.next();
if (min.compareTo(next) > 0)
min = next;
****************************************************
How to remove this min item?
****************************************************
}
return min;
}
What is this Comparable thing?
It is a generic interface that can be implemented by classes whose instances you need to be able to compare with each other. Comparable<T> has a single method int compareTo<other T>. The implementation of the method is supposed to compare this with the other instance
In my sample code, why class Bag<T extends Comparable<T>>? What's the purpose?
This is saying that your Bag class is a generic class with a type parameter T. The T extends Comparable<T> bits is saying that T must be some class that implements Comparable<T>.
My second question is how to remove an item from this Comparable array.
That is for you to figure out, based on your knowledge of how arrays work. The big constraint you have to deal with is that an array's size cannot be changed, so there is no magical operation that will simply remove something from the middle of the array.
There are two approaches:
Create a new array containing just the elements that you don't want to be removed. (Hint: copy them)
Move the elements around in the existing array to "fill the hole" left when you conceptually remove an element. (Hint: notice the size field. What is it there for?)
Assuming that you wrote the removeMin method from scratch, I think you have gone down a blind alley with trying to use an iterator there1. Try coding it to operate directly on the data array.
The removeMin problem has two parts:
Find the index in data for the smallest element
Remove the element at that index
Hint: the first part requires that you look at every element ... and this has to be done before you do the removal. This should be reflected in your code.
1 - If you were using an ArrayList<T> or similar, then using data.iterator() would be a reasonable choice. The problem is that arrays don't directly support the Iterable API.
Now if you are required to make your Bag class implement Iterable<T>, then you could use the iteration mechanism you implemented for that purpose in your removeMin method. But even there, the API is not ideal for the purpose. You would still need to iterate the collection twice. Once to find the smallest element, and a second time to remove it. And removal via an iterator means that the iterator would need to implement the optional Iterator.remove() method .... which brings you back full circle.
It is the java.lang.Comparable interface. <T extends Comparable<T>> is a generic type, at compile time Java will require that an instance provide an implementation of int compareTo(T o) which (from the Javadoc) returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. Also, you might back your Bag with a Collection (instead of an array), like
class Bag<T extends Comparable<T>> implements Iterable<T> {
private List<T> al = new ArrayList<>();
public Bag() {
super();
}
public T removeMin() {
Iterator<T> iterator = iterator();
T min = iterator.hasNext() ? iterator.next() : null;
while (iterator.hasNext()) {
T next = iterator.next();
if (min.compareTo(next) > 0) {
min = next;
}
}
if (min != null) {
iterator = iterator();
while (iterator.hasNext()) {
T next = iterator.next();
if (min.compareTo(next) == 0) {
iterator.remove();
break;
}
}
}
return min;
}
#Override
public Iterator<T> iterator() {
return al.iterator();
}
}
Note that Iterator.remove() says (in part) the behavior of an iterator is unspecified if the underlying collection is modified while the iteration is in progress in any way other than by calling this method.
The comparable interface is implemented in order to define a comparison mechanism to your custom types.
array are usually size fixed so you cannot just remove an item without copying the remaining ones to a new array. I suggest to change your array to dynamic list:
public class Bag<T extends Comparable<T>> implements Iterable<T> {
private int size;
private LinkedList<T> data;
public Bag() {
data = new LinkedList<T>();
size = 0;
}
public Comparable removeMin() {
Iterator<T> iterator = iterator();
T min = iterator.next();
while (iterator.hasNext()) {
T next = iterator.next();
if (min.compareTo(next) > 0)
min = next;
data.remove(min);
}
return min;
}
}
what is this Comparable thing
In simplest term it specifies how the items can be compared to each other . For example in your case your class Bag may contain any item so you used generic type T but you want your items to be comparable to each other too, so you used T extends Comparable<T>
The Comparable interface has a method compareTo which is used to compare the items. You can read more about it in JLS.
Now you may be wondering why do I need to compare items?
Imagine if you have no way to compare then how can you say 5 is a bigger number than 1 or why A comes before B in alphabets. They do so because we have some order for them and based on them we can compare then. Similarly you may like a items in your bag to be comparable.
how to remove an item from this Comparable array
To iterate over the items you already seem to use an iterator
Iterator<T> iterator=iterator();
T min = iterator.next();
You can use same iterator to remove the item if it matches your condition. So your code should be iterator.remove(). But you should also ensure for null check and existence check at all relevant places
The method signature looks like this:
public void addThemAll(Collection<? extends T> c)
Which essentially just adds every element of the collection to my LinkedList. But I keep trying to feed this method an Array or a Linked List and I always get an error. For example:
double[] myarray = new double[]{3.4, 4.5, 8.6};
mylist.addThemAll(myarray);
I'm sure this is something straightforward, but I can't find an example online that just passes an array/linked list into a method like this.
Your code has two problems:
An array is not a collection. It does not extend Collection. Therefore, you can't pass it into a method whose signature specifies a collection parameter.
You have not defined <T> (or, at least, you have not shown us where you are defining <T>). You can either define <T> in your class, or in your method signature.
To define it in your class, do it like this:
public class MyClass<T> {
// contents
}
To define <T> in your method, do it like this:
public <T> void addThemAll(Collection<? extends T> c) {
// method logic
}
For what you are doing, this would work:
List<Double> myArray = Arrays.asList(3.4, 4.5, 8.6);
mylist.addThemAll(myarray);
The reason being is that you are passing in a list (which is a collection). Currently you are passing in an Array, which is not a collection.
To pass in the array to collection:
Double[] myarray = new Double[]{3.4, 4.5, 8.6};
mylist.addThemAll(Arrays.asList(myarray));
if you don't want it as list but want it as LinkedList or etc
LinkedList<Double> linkedlist = new LinkedList(Arrays.asList(myarray));
mylist.addThemAll(linkedlist);
if you want to use set or treeset
TreeSet <Double> treeset = new TreeSet(linkedlist);
Difference between set and list is that set does not have duplicate and not ordered, and list is ordered but contains duplicates.
After you pass in to your method:
public void addThemAll(Collection<? extends T> c)
if(c instanceof LinkedList){
LinkedList a = (LinkedList) c //you can invoke methods from LinkedList
....
}
I am following along with this example of Quicksort implemented in Java, on Rosettacode. From what I understand this is supposed to take in an array of things that implement the Comparable interface, and that the type is inferred during runtime. I wrapped this up in a little class with a main method, but get an slew of errors about the inferred type. I am relative new to Java and not familiar with this construct yet.
import java.util.List;
import java.util.LinkedList;
public class QuickSortExample {
public static <E extends Comparable<? super E>> List<E> quickSort(List<E> arr) {
if (arr.size() <= 1) return arr;
E pivot = arr.getFirst();
List<E> less = new LinkedList<E>();
List<E> pivotList = new LinkedList<E>();
List<E> more = new LinkedList<E>();
for (E i: arr) {
if (i.compareTo(pivot) < 0) less.add(i);
else if (i.compareTo(pivot) > 0) more.add(i);
else pivotList.add(i);
}
less = quickSort(less);
more = quickSort(more);
less.addAll(pivotList);
less.addAll(more);
return less;
}
public static void main(String[] args){
int[] myArray = new int[]{2,3,1,6,2,87,5,3,546,9,2,3,8,111};
int[] mySortedArray = quickSort(myArray);
System.out.println(mySortedArray);
}
}
And I get these errors on compile
$ javac QuickSortExample.java
QuickSortExample.java:11: cannot find symbol
symbol : method getFirst()
location: interface java.util.List<E>
E pivot = arr.getFirst();
^
QuickSortExample.java:37: <E>quickSort(java.util.List<E>) in QuickSortExample cannot be applied to (int[])
int[] mySortedArray = quickSort(myArray);
^
2 errors
I have 3 questions.
1) What does the ? mean in the following statement?
<E extends Comparable<? super E>> List<E> quickSort(List<E> arr)
2) It seems like this is made to work on LinkedList objects, due to the getFirst() method. Is that correct? If so, can I get this to work on a general List? Would I have to cast my Array of ints as List. I'm a little confused here. I have been consulting both the List and LinkedList javadocs.
3) Can I accomplish this all with the List object, instead of LinkedList? Is there a reason LinkedList was chosen for this example that I dont understand? Also, if I wanted to call this with an Array of Integers, would I have to cast(?) that input differently on the way in since it doesnt look like Array inherits from List?
Sorry for the really basic questions, just learning Java for real for the first time.
The quick sort method accepts a List of objects of Type X and returns a List of type of X. Type X should implement the Comparable interface with generic type of X
You can use the method Arrays.asList(<your-array>) to convert the array to a list
There is no mention of LinkedList in the method contract, you can pass any type of List to the quickSort method and it will return an object of type List. LinkedList is an implementation of List used internally by the method.
Ex:
Integer[] arr = { 1, 2, 3 };
List<Integer> asList = Arrays.asList(arr);
quickSort(asList);
I have changed your code in main method to the following one:
public static void main(String[] args){
Integer[] arr = {2,3,1,6,2,87,5,3,546,9,2,3,8,111};
List<Integer> asList = Arrays.asList(arr);
List<Integer> mySortedArray = quickSort(asList);
System.out.println(mySortedArray);
}
the algorithm is perfectly working now.
I try to add objects to a List<String> instance but it throws an UnsupportedOperationException.
Does anyone know why?
My Java code:
String[] membersArray = request.getParameterValues('members');
List<String> membersList = Arrays.asList(membersArray);
for (String member : membersList) {
Person person = Dao.findByName(member);
List<String> seeAlso;
seeAlso = person.getSeeAlso();
if (!seeAlso.contains(groupDn)){
seeAlso.add(groupDn);
person.setSeeAlso(seeAlso);
}
}
The error message:
java.lang.UnsupportedOperationException
java.util.AbstractList.add(Unknown Source)
java.util.AbstractList.add(Unknown Source)
javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
Not every List implementation supports the add() method.
One common example is the List returned by Arrays.asList(): it is documented not to support any structural modification (i.e. removing or adding elements) (emphasis mine):
Returns a fixed-size list backed by the specified array.
Even if that's not the specific List you're trying to modify, the answer still applies to other List implementations that are either immutable or only allow some selected changes.
You can find out about this by reading the documentation of UnsupportedOperationException and List.add(), which documents this to be an "(optional operation)". The precise meaning of this phrase is explained at the top of the List documentation.
As a workaround you can create a copy of the list to a known-modifiable implementation like ArrayList:
seeAlso = new ArrayList<>(seeAlso);
Many of the List implementation support limited support to add/remove, and Arrays.asList(membersArray) is one of that. You need to insert the record in java.util.ArrayList or use the below approach to convert into ArrayList.
With the minimal change in your code, you can do below to convert a list to ArrayList. The first solution is having a minimum change in your solution, but the second one is more optimized, I guess.
String[] membersArray = request.getParameterValues('members');
ArrayList<String> membersList = new ArrayList<>(Arrays.asList(membersArray));
OR
String[] membersArray = request.getParameterValues('members');
ArrayList<String> membersList = Stream.of(membersArray).collect(Collectors.toCollection(ArrayList::new));
Form the Inheritance concept, If some perticular method is not available in the current class it will search for that method in super classes. If available it executes.
It executes AbstractList<E> class add() method which throws UnsupportedOperationException.
When you are converting from an Array to a Collection Obejct. i.e., array-based to collection-based API then it is going to provide you fixed-size collection object, because Array's behaviour is of Fixed size.
java.util.Arrays.asList( T... a )
Souce samples for conformation.
public class Arrays {
public static <T> List<T> asList(T... a) {
return new java.util.Arrays.ArrayList.ArrayList<>(a); // Arrays Inner Class ArrayList
}
//...
private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable {
//...
}
}
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
//...
}
public ListIterator<E> listIterator() {
return listIterator(0);
}
private class ListItr extends Itr implements ListIterator<E> {
//...
}
}
Form the above Source you may observe that java.util.Arrays.ArrayList class doesn't #Override add(index, element), set(index, element), remove(index). So, From inheritance it executes super AbstractList<E> class add() function which throws UnsupportedOperationException.
As AbstractList<E> is an abstract class it provides the implementation to iterator() and listIterator(). So, that we can iterate over the list object.
List<String> list_of_Arrays = Arrays.asList(new String[] { "a", "b" ,"c"});
try {
list_of_Arrays.add("Yashwanth.M");
} catch(java.lang.UnsupportedOperationException e) {
System.out.println("List Interface executes AbstractList add() fucntion which throws UnsupportedOperationException.");
}
System.out.println("Arrays → List : " + list_of_Arrays);
Iterator<String> iterator = list_of_Arrays.iterator();
while (iterator.hasNext()) System.out.println("Iteration : " + iterator.next() );
ListIterator<String> listIterator = list_of_Arrays.listIterator();
while (listIterator.hasNext()) System.out.println("Forward iteration : " + listIterator.next() );
while(listIterator.hasPrevious()) System.out.println("Backward iteration : " + listIterator.previous());
You can even create Fixed-Size array form Collections class Collections.unmodifiableList(list);
Sample Source:
public class Collections {
public static <T> List<T> unmodifiableList(List<? extends T> list) {
return (list instanceof RandomAccess ?
new UnmodifiableRandomAccessList<>(list) :
new UnmodifiableList<>(list));
}
}
A Collection — sometimes called a container — is simply an object that groups multiple elements into a single unit. Collections are used to store, retrieve, manipulate, and communicate aggregate data.
#see also
HashMap vs HashTable
Object Serialization uses the Serializable and Externalizable interfaces
You will also get this exception if you attempt to add to a List<T> returned by Collections.singletonList(T o):
Returns an immutable list containing only the specified object. The returned list is serializable.
The JVM does not implement add() for Collections.singletonList
List membersList = Arrays.asList(membersArray);
returns immutable list, what you need to do is
new ArrayList<>(Arrays.asList(membersArray)); to make it mutable
You must initialize your List seeAlso :
List<String> seeAlso = new Vector<String>();
or
List<String> seeAlso = new ArrayList<String>();
You cannot modify a result from a LDAP query. Your problem is in this line:
seeAlso.add(groupDn);
The seeAlso list is unmodifiable.
instead of using add() we can use addall()
{ seeAlso.addall(groupDn); }
add adds a single item, while addAll adds each item from the collection one by one. In the end, both methods return true if the collection has been modified. In case of ArrayList this is trivial, because the collection is always modified, but other collections, such as Set, may return false if items being added are already there.