How to reverse an unmodifiable List in java - java

I am trying to reverse an unmodifiable list. However i have tried to achieve it but Is it possible to update or reverse and unmodifiable list? I know we can do it with Google Immutable List
import java.util.*;
public class ImmutableList
{
public static void main(String args[])
{
String[] mylist = {"Apple","Orange","Mango","Kiwi","Banana"};
List reverselist = new ArrayList();
List<String> strList = Arrays.asList(mylist);
List<String> unmodifiableList = Collections.unmodifiableList(strList);
for(int i=unmodifiableList.size();i>0;i--)
{
reverselist.add(unmodifiableList.get(i-1));
}
List<String> reverse = Collections.unmodifiableList(reverselist);
System.out.println(reverse);
}
}
In the above program I am just traversing in unmodifable list from back and putting them in an array after that adding that array to new unmodifiable list. Can we do it in better way in terms of optimisation?

Guava's Lists.reverse(List) returns a reversed view of the original list, without doing any copying.

When the list is unmodifiable anyhow, you can just create a reversed view on the list.
This is optimal in terms of performance and storage: It requires O(1) time and O(1) additional space to create this list.
import java.util.AbstractList;
import java.util.Arrays;
import java.util.List;
public class ReversedListViewTest
{
public static void main(String[] args)
{
String[] array = {"Apple","Orange","Mango","Kiwi","Banana"};
List<String> list = Arrays.asList(array);
System.out.println("List : "+list);
List<String> reversedView = reversedView(list);
System.out.println("Reversed view: "+reversedView);
}
private static <T> List<T> reversedView(final List<T> list)
{
return new AbstractList<T>()
{
#Override
public T get(int index)
{
return list.get(list.size()-1-index);
}
#Override
public int size()
{
return list.size();
}
};
}
}

May be not the best solution but better then reverse ourself:
public List<T> reverseUnModList(List<T> unModListOrig) {
List<T> tmpList = new ArrayList<T>(unModListOrig);
Collections.reverse(tmpList);
return Collections.unmodifiableList(unModListOrig);
//return tmpList; //if the result not need to be unmodifieable
}

Related

Custom iterator won't print anything when trying to iterate through an ArrayList

I'm very new to iterators but for an assignment I wrote a custom Iterator and I want to simply print out object as I iterate through a list of them but it keeps printing nothing and I have no idea why.
Here's the custom iterator code:
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
public class MyList<T> implements Iterable<T> {
private List<T> list;
private class MyIterator<t> implements Iterator<t> {
int lSize = list.size();
int lPoint = 0;
public boolean hasNext() {
return (lPoint < lSize);
}
public t next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
t val = (t) list.get(lPoint);
lPoint++;
return val;
}
}
public MyList(List<T> list) {
this.list = list;
}
public Iterator<T> iterator() {
return new MyIterator<>();
}
}
Here's the class I'm using to test it:
Public class TestCloning {
Electronics test = new Electronics("Test", 100, 10);
Electronics test3 = new Electronics("Test2", 300, 30);
List<Electronics> order1 = new ArrayList<>();
MyList<Electronics> mList1 = new MyList<>(order1);
Iterator<Electronics> mIterator1 = mList1.iterator();
public void testIterator(){
order1.add(test);
order1.add(test3);
while (mIterator1.hasNext()){
System.out.println(mIterator1.next().toString());
}
}
}
This is mainly because the lSize=0
The reason why it is zero is because you add the list of things to myList before you actually add any items into that list.
List<String> order1 = new ArrayList<>();
order1.add(test);
order1.add(test3);
MyList<String> mList1 = new MyList<>(order1);
Iterator<String> mIterator1 = mList1.iterator();
If you flip the order, add things to the order list, then create your custom one everything will work as you'd expect.
Also, I suggest in the future, don't use any custom iterators or lists that wrap normal lists. I understand this is for the purpose of an assignment, and then acceptable

Iterator print LinkedList

I have a problem regarding the display of my LinkedList with a foreach.
When I want to display my LikedList an error comes from my list which tells me that I have to use an iterator. Here is the code:
public class Set {
private LinkedList <Integer> elements;
public Set () {
this.elements = new LinkedList <Integer> ();
}
public static void main (String [] args) {
Set test = new Set ();
test.add (8);
test.add (2);
test.add (7);
for (int e: test) {
}
}
So I used an iterator for the display but a message tells me that my iterator is undefined for the method set.
Here is the code:
public class Set {
private LinkedList <Integer> elements;
public Set () {
this.elements = new LinkedList <Integer> ();
}
public static void main (String [] args) {
Set test = new Set ();
test.add (8);
test.add (2);
test.add (7);
Iterator <Integer> iterator = test.iterator ();
while (iterator.hasNext ()) {
System.out.println (iterator.next ());
}
}
If you can help me with that, it will help me a lot.
(I tried to define "Iterator <Integer> iterator = this.elements.iterator ();" in the Set () public and call it in the hand that way but without success "while (iterator.hasNext ()) {
System.out.println (iterator.next ());
}")
Thank you in advance, nice day
Your Set class needs to implement iterable interface as
public class Set implements Iterable<Integer> {
private LinkedList<Integer> elements;
public Set() {
this.elements = new LinkedList<Integer>();
}
#Override
public Iterator<Integer> iterator() {
return elements.iterator();
}
}
Your class Set doesn't define an iterator you should add for example a method like that one:
public Iterator<Integer> getIterator() {
return elements.iterator();
}

How to cause permutation event by manipulating ObservableList?

ObservableList listeners can receive Change events with permutation set.
Simultaneously, among list operations, I see only ones to delete or insert elements.
Is it possible to perform such operation on list, which will cause permutation reported?
UPDATE
Here is the clarification code:
public class ObservableListPermutation {
public static void main(String[] args) {
ObservableList<String> list = FXCollections.observableArrayList();
list.add("timbuktu");
list.add("timid");
list.addListener(new ListChangeListener<String>() {
#Override
public void onChanged(Change<? extends String> c) {
while(c.next()) {
if( c.wasPermutated() ) {
System.out.println("Was permutated");
}
}
}
});
System.out.println("Sorting by library:");
Collections.sort(list);
System.out.println("Sorting by own:");
Collections2.sort(list);
}
public static class Collections2 {
public static void sort(List<String> list) {
String element = list.remove(0);
list.add(element);
}
}
}
As you see, my custom permutation does not cause permutation event, because it is done by removing and adding elements. How to implement custom permutation, so that it cause permutation event?
UPDATE 2
If I try to trace sort() with debugger, I am unable to enter the code of sort().
To elaborate on #ItachiUchiha's answer and #fabian's comment, any single operation that modifies an ObservableList will notify change listeners. So there is no way to trigger a "permutation event" on an ObservableList by calling a sequence of operations that each modify the list (each operation would notify listeners independently).
So to support permutations that are not supported out of the box (i.e. by FXCollections.sort(), FXCollections.shuffle(), FXCollections.rotate(), and FXCollections.reverse()), you need to implement your own ObservableList, defining (or possibly overriding) single entry-point methods that trigger a permutation. The ModifiableObservableListBase class provides a convenient starting point.
Here is a simple example:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javafx.collections.ModifiableObservableListBase;
public class PermutatingObservableList<E> extends ModifiableObservableListBase<E> {
private final List<E> source ;
public PermutatingObservableList(List<E> source) {
this.source = source ;
}
public void permute(int[] permutation) {
checkPermutation(permutation);
beginChange();
List<E> temp = new ArrayList<>(source);
for (int i = 0 ; i < size() ; i++) {
source.set(i, temp.get(permutation[i]));
}
nextPermutation(0, size(), permutation);
endChange();
}
public void pairwiseSwap() {
int[] permutation = new int[size()];
for (int i = 0; i+1 < permutation.length ; i+=2) {
permutation[i] = i+1 ;
permutation[i+1] = i ;
}
if (permutation.length % 2 == 1) {
permutation[permutation.length - 1] = permutation.length - 1 ;
}
permute(permutation);
}
private void checkPermutation(int[] permutation) {
boolean valid = permutation.length == size();
Set<Integer> values = IntStream.range(0, size()).boxed().collect(Collectors.toSet());
for (int i=0; i<permutation.length && valid ; i++) {
valid = values.remove(new Integer(permutation[i]));
}
if (! valid) {
throw new IllegalArgumentException("Invalid permuation: "+Arrays.toString(permutation)+"\n"
+"Permutation must be same length as list and must contain each of the values "
+ "0-"+(size()-1)+" exactly once");
}
}
#Override
public E get(int index) {
return source.get(index);
}
#Override
public int size() {
return source.size();
}
#Override
protected void doAdd(int index, E element) {
source.add(index, element);
}
#Override
protected E doSet(int index, E element) {
return source.set(index, element);
}
#Override
protected E doRemove(int index) {
return source.remove(index);
}
}
and a test:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javafx.collections.ListChangeListener;
public class PermutingObservableListTest {
public static void main(String[] args) {
List<String> numbers = Arrays.asList("One", "Two", "Three", "Four", "Five");
PermutatingObservableList<String> list = new PermutatingObservableList<>(new ArrayList<>(numbers));
list.addListener(new ListChangeListener<String>() {
#Override
public void onChanged(Change<? extends String> c) {
while (c.next())
System.out.println(c.wasPermutated());
System.out.println(IntStream.range(0, list.size())
.map(c::getPermutation)
.mapToObj(Integer::toString)
.collect(Collectors.joining(", ")));
}
}
});
list.pairwiseSwap();
System.out.println(list);
}
}
which produces the output
true
1, 0, 3, 2, 4
[Two, One, Four, Three, Five]
A very simple operation a List to report Permutation would be to sort the items in the List.
For example, the following code would print true.
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import java.util.Collections;
public class PermutationTest {
public static void main(String[] args) {
ObservableList<String> list =
FXCollections.observableArrayList("Z", "Y", "X");
list.addListener(new ListChangeListener<String>() {
#Override
public void onChanged(Change<? extends String> c) {
c.next();
System.out.println(c.wasPermutated());
}
});
Collections.sort(list);
}
}
Answers to additional question :
I would like to cause it myself, without calling black box methods. Suppose I have instance of ObservableList and nothing more and would like to code some manipulation, which causes permutation, How would I do this?
This is not possible if you are using the ObservableList provided by FXCollections util class because of the way ObservableList is implemented in it.
Considering the following points :
Whenever you add or remove elements a MappingChange is triggered.
ListChangeListener#wasPermutated() checks if length of the int array returned by getPermutation() is greater than zero.
In case of MappingChange, the getPermuatation() always returns an int of length 0.
Now, you must be wondering (like I was), how does it work when we do a sort on the same List?
It turns out the ObservableListWrapper (which is the base for creating list in FXCollections) overrides sort() and then forces a SimplePermutationChange.
Is there an alternative?
You can create your own custom ObservableList by extending ModifiableObservableListBase as stated by this comment and shown in this answer.

Implementing a List data structure in java

I have a homework about implementing lists in java. I have written a code, and a method about displaying the elements, but when I run it, it says there is an error in this method. can you please help me fix this?
here is my code:
public class Lista {
public int num;
public Lista pas;
public Lista(int num){
this.num = num;
}
public void display(){
System.out.println(num);
}
public static void main(String[] args){
linkedList l = new linkedList();
l.insertfirst(1);
l.insertfirst(3);
l.insertfirst(5);
l.display();
}
}
class linkedList{
public Lista LIST;
public Lista pozicion;
linkedList(){
LIST = null;
}
public void insert(int num, Lista pozicion){
Lista temp = pozicion.pas;
Lista l = new Lista(num);
pozicion.pas.num = num;
pozicion.pas.pas = temp;
}
public void delete(Lista pozicion){
pozicion.pas = pozicion.pas.pas;
}
public Lista locate(int num, Lista LIST){
pozicion = LIST;
while (pozicion.pas != null){
if (pozicion.pas.num == num){
return pozicion;
}else{
pozicion = pozicion.pas;
}
}
return pozicion;
}
public void insertfirst(int num){
Lista eRe = new Lista(num);
eRe.pas = LIST;
LIST = eRe;
}
}
Well, for starters...
display() is not a method of class linkedList (note: naming convention should be LinkedList).
display() is a method of Lista. That is why the IDE is telling you 'display() is undefined for the type linkedList'
Just quickly looking at your code for what you need to do... You need to implement a get() (or perhaps a solution to get the first element of the linkedList and from there iterate through the linkedList) method in the linkedList class which returns a Lista object. With that Lista object, you can then call the method .display() on it.

Is it possible to merge iterators in Java?

Is it possible to merge iterators in Java? I have two iterators and I want to combine/merge them so that I could iterate though their elements in one go (in same loop) rather than two steps. Is that possible?
Note that the number of elements in the two lists can be different therefore one loop over both lists is not the solution.
Iterator<User> pUsers = userService.getPrimaryUsersInGroup(group.getId());
Iterator<User> sUsers = userService.getSecondaryUsersInGroup(group.getId());
while(pUsers.hasNext()) {
User user = pUsers.next();
.....
}
while(sUsers.hasNext()) {
User user = sUsers.next();
.....
}
Guava (formerly Google Collections) has Iterators.concat.
Also the Apache Commons Collection have several classes for manipulating Iterators, like the IteratorChain, that wraps a number of Iterators.
You could create your own implementation of the Iterator interface which iterates over the iterators:
public class IteratorOfIterators implements Iterator {
private final List<Iterator> iterators;
public IteratorOfIterators(List<Iterator> iterators) {
this.iterators = iterators;
}
public IteratorOfIterators(Iterator... iterators) {
this.iterators = Arrays.asList(iterators);
}
public boolean hasNext() { /* implementation */ }
public Object next() { /* implementation */ }
public void remove() { /* implementation */ }
}
(I've not added generics to the Iterator for brevity.) The implementation is not too hard, but isn't the most trivial, you need to keep track of which Iterator you are currently iterating over, and calling next() you'll need to iterate as far as you can through the iterators until you find a hasNext() that returns true, or you may hit the end of the last iterator.
I'm not aware of any implementation that already exists for this.
Update:
I've up-voted Andrew Duffy's answer - no need to re-invent the wheel. I really need to look into Guava in more depth.
I've added another constructor for a variable number of arguments - almost getting off topic, as how the class is constructed here isn't really of interest, just the concept of how it works.
I haven't written Java code in a while, and this got me curious to whether I've still "got it".
First try:
import java.util.Iterator;
import java.util.Arrays; /* For sample code */
public class IteratorIterator<T> implements Iterator<T> {
private final Iterator<T> is[];
private int current;
public IteratorIterator(Iterator<T>... iterators)
{
is = iterators;
current = 0;
}
public boolean hasNext() {
while ( current < is.length && !is[current].hasNext() )
current++;
return current < is.length;
}
public T next() {
while ( current < is.length && !is[current].hasNext() )
current++;
return is[current].next();
}
public void remove() { /* not implemented */ }
/* Sample use */
public static void main(String... args)
{
Iterator<Integer> a = Arrays.asList(1,2,3,4).iterator();
Iterator<Integer> b = Arrays.asList(10,11,12).iterator();
Iterator<Integer> c = Arrays.asList(99, 98, 97).iterator();
Iterator<Integer> ii = new IteratorIterator<Integer>(a,b,c);
while ( ii.hasNext() )
System.out.println(ii.next());
}
}
You could of course use more Collection classes rather than a pure array + index counter, but this actually feels a bit cleaner than the alternative. Or am I just biased from writing mostly C these days?
Anyway, there you go. The answer to you question is "yes, probably".
public class IteratorJoin<T> implements Iterator<T> {
private final Iterator<T> first, next;
public IteratorJoin(Iterator<T> first, Iterator<T> next) {
this.first = first;
this.next = next;
}
#Override
public boolean hasNext() {
return first.hasNext() || next.hasNext();
}
#Override
public T next() {
if (first.hasNext())
return first.next();
return next.next();
}
}
Starting with Java 8 and later this can be done without external dependencies using Stream API. This also allows concatenation of iterator with other types of streams.
Streams.concat(StreamSupport.stream(<iter1>, false), StreamSupport.stream(<iter2>, false));
move your loop to a method and pass the iterator to method.
void methodX(Iterator x) {
while (x.hasNext()) {
....
}
}
an iterator comes FROM a collection or a set.
why not use the method already available
Collection.addAll(Collection c);
and then create your iterator from the last object.
this way, your iterator will iterate all the contents of both collection.
You can use my version of an extendable iterator. It uses a double-ended queue of iterators which to me makes sense:
import java.util.Deque;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedDeque;
public class ExtendableIterator<T> implements Iterator<T> {
public Deque<Iterator<T>> its = new ConcurrentLinkedDeque<Iterator<T>>();
public ExtendableIterator() {
}
public ExtendableIterator(Iterator<T> it) {
this();
this.extend(it);
}
#Override
public boolean hasNext() {
// this is true since we never hold empty iterators
return !its.isEmpty() && its.peekLast().hasNext();
}
#Override
public T next() {
T next = its.peekFirst().next();
if (!its.peekFirst().hasNext()) {
its.removeFirst();
}
return next;
}
public void extend(Iterator<T> it) {
if (it.hasNext()) {
its.addLast(it);
}
}
}
The Merged Iterator:
import static java.util.Arrays.asList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
public class ConcatIterator<T> implements Iterator<T> {
private final List<Iterable<T>> iterables;
private Iterator<T> current;
#SafeVarargs
public ConcatIterator(final Iterable<T>... iterables) {
this.iterables = new LinkedList<>(asList(iterables));
}
#Override
public boolean hasNext() {
checkNext();
return current != null && current.hasNext();
}
#Override
public T next() {
checkNext();
if (current == null || !current.hasNext()) throw new NoSuchElementException();
return current.next();
}
#Override
public void remove() {
if (current == null) throw new IllegalStateException();
current.remove();
}
private void checkNext() {
while ((current == null || !current.hasNext()) && !iterables.isEmpty()) {
current = iterables.remove(0).iterator();
}
}
}
The concat method to create an Iterable:
#SafeVarargs
public static <T> Iterable<T> concat(final Iterable<T>... iterables) {
return () -> new ConcatIterator<>(iterables);
}
Simple JUnit test:
#Test
public void testConcat() throws Exception {
final Iterable<Integer> it1 = asList(1, 2, 3);
final Iterable<Integer> it2 = asList(4, 5);
int j = 1;
for (final int i : concat(it1, it2)) {
assertEquals(j, i);
j++;
}
}
I would refactor the original design from:
Iterator<User> pUsers = userService.getPrimaryUsersInGroup(group.getId());
Iterator<User> sUsers = userService.getSecondaryUsersInGroup(group.getId());
To something like:
Iterator<User> users = userService.getUsersInGroup(group.getId(), User.PRIMARY, User.SECONDARY, ...);
You can try ConcatIterator from Cactoos:
Iterator<String> names = new ConcatIterator<>(
Arrays.asList("Sarah", "Mary").iterator(),
Arrays.asList("Jeff", "Johnny").iterator(),
);
Also check ConcatIterable, which concatenates Iterables.
In the Apache Commons Collections there is public static <E> Iterator<E> org.apache.commons.collections4.IteratorUtils.chainedIterator(Collection<Iterator<? extends E>> iterators) that says
Gets an iterator that iterates through a collections of Iterators one after another.
which should be what you want.
import java.util.Arrays;
import java.util.Iterator;
import org.apache.commons.collections4.IteratorUtils;
//also works: import org.apache.commons.collections.IteratorUtils;
class Scratch {
public static void main( String[] args ) {
final Iterator<String> combinedIterator = IteratorUtils.chainedIterator(
Arrays.asList( "a", "b", "c" ).iterator(),
Arrays.asList( "1", "2", "3" ).iterator()
);
while( combinedIterator.hasNext() ){
System.out.println( combinedIterator.next() );
}
// "abc123" will have been printed out
}
}
every Iterator object holds own memory location (adress), so you can't simply "merge" them. except if you extend iterator class and write your own implementation there.
If you are dealing with the same number of objects in both iterators an alternative solution would be to process two iterators in one loop like this :
while (iterator1.hasNext() && iterator2.hasNext()) {
// code
}

Categories