|
|
@@ -0,0 +1,291 @@
|
|
|
+/*
|
|
|
+ * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
+ * @copyright Ranides Atterwim
|
|
|
+ * @license WTFPL
|
|
|
+ * @url http://ranides.net/projects/assira
|
|
|
+ */
|
|
|
+package net.ranides.assira.collection.lists;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Klasa reprezentująca złączenie wielu list jako jedną kolekcję.
|
|
|
+ * @param <T>
|
|
|
+ * @author ranides
|
|
|
+ * @todo (migration) assira
|
|
|
+ */
|
|
|
+public class JoinList<T> extends AbstractSequentialList<T> {
|
|
|
+
|
|
|
+ private final List<List<T>> content;
|
|
|
+
|
|
|
+ public JoinList() {
|
|
|
+ content = new LinkedList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public JoinList(List<T>... values) {
|
|
|
+ this();
|
|
|
+ joinAll(Arrays.asList(values));
|
|
|
+ }
|
|
|
+
|
|
|
+ public JoinList(List<List<T>> values) {
|
|
|
+ this();
|
|
|
+ joinAll(values);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Dodaje do kolekcji kolejną listę. Uwaga: dodawana jest <b>lista</b>, a nie
|
|
|
+ * jej elementy.
|
|
|
+ * @param list
|
|
|
+ * @return this
|
|
|
+ */
|
|
|
+ public JoinList<T> join(List<T> list) {
|
|
|
+ content.add(list);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Dodaje do kolekcji kolejną listę. Uwaga: dodawana jest <b>lista</b>, a nie
|
|
|
+ * jej elementy.
|
|
|
+ * @param list
|
|
|
+ * @return this
|
|
|
+ */
|
|
|
+ public JoinList<T> join(int index, List<T> list) {
|
|
|
+ content.add(index, list);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /***
|
|
|
+ * Dodaje do kolekcji kolejne listy. Uwaga: dodawane są <b>listy</b>, a nie
|
|
|
+ * ich elementy.
|
|
|
+ * @param list
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public final JoinList<T> joinAll(List<List<T>> list) {
|
|
|
+ content.addAll(list);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Dodaje do kolekcji kolejne listy. Uwaga: dodawane są <b>listy</b>, a nie
|
|
|
+ * ich elementy.
|
|
|
+ * @param list
|
|
|
+ * @return this
|
|
|
+ */
|
|
|
+ public final JoinList<T> joinAll(int index, List<List<T>> list) {
|
|
|
+ content.addAll(index, list);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int size() {
|
|
|
+ int size = 0;
|
|
|
+ for(List<T> list : content) {
|
|
|
+ size += list.size();
|
|
|
+ }
|
|
|
+ return size;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean contains(Object value) {
|
|
|
+ for(List<T> list : content) {
|
|
|
+ if( list.contains(value) ) { return true; }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public T get(int index) {
|
|
|
+ int begin, end = 0;
|
|
|
+ for(List<T> list : content) {
|
|
|
+ begin = end;
|
|
|
+ end += list.size();
|
|
|
+ if(index < end) {
|
|
|
+ return list.get(index - begin);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ throw new IndexOutOfBoundsException("index=" + index + " size=" + end );
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void add(int index, T element) {
|
|
|
+ int begin, end = 0;
|
|
|
+ for(List<T> list : content) {
|
|
|
+ begin = end;
|
|
|
+ end += list.size();
|
|
|
+ if(index < end) {
|
|
|
+ list.add(index - begin, element);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ throw new IndexOutOfBoundsException("index=" + index + " size=" + end );
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean addAll(int index, Collection<? extends T> values) {
|
|
|
+ int begin, end = 0;
|
|
|
+ for(List<T> list : content) {
|
|
|
+ begin = end;
|
|
|
+ end += list.size();
|
|
|
+ if(index < end) {
|
|
|
+ return list.addAll(index - begin, values);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ throw new IndexOutOfBoundsException("index=" + index + " size=" + end );
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public T remove(int index) {
|
|
|
+ int begin, end = 0;
|
|
|
+ for(List<T> list : content) {
|
|
|
+ begin = end;
|
|
|
+ end += list.size();
|
|
|
+ if(index < end) {
|
|
|
+ return list.remove(index - begin);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ throw new IndexOutOfBoundsException("index=" + index + " size=" + end );
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public T set(int index, T element) {
|
|
|
+ int begin, end = 0;
|
|
|
+ for(List<T> list : content) {
|
|
|
+ begin = end;
|
|
|
+ end += list.size();
|
|
|
+ if(index < end) {
|
|
|
+ return list.set(index - begin, element);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ throw new IndexOutOfBoundsException("index=" + index + " size=" + end );
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ListIterator<T> listIterator(int index) {
|
|
|
+ return new JoinIterator(content, index);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static final class JoinIterator<T> implements ListIterator<T> {
|
|
|
+
|
|
|
+ private ListIterator<List<T>> li;
|
|
|
+ private ListIterator<T> ci;
|
|
|
+ private int csize;
|
|
|
+ private int begin;
|
|
|
+
|
|
|
+ public JoinIterator(List<List<T>> data, int index) {
|
|
|
+ li = data.listIterator();
|
|
|
+ csize = 0;
|
|
|
+ ci = null;
|
|
|
+
|
|
|
+ if(index == 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ while(li.hasNext()) {
|
|
|
+ begin += csize;
|
|
|
+ index -= begin;
|
|
|
+
|
|
|
+ List<T> list = li.next();
|
|
|
+ csize = list.size();
|
|
|
+
|
|
|
+ if(index < begin) {
|
|
|
+ ci = list.listIterator(index - begin);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ throw new IndexOutOfBoundsException("index=" + index);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean hasNext() {
|
|
|
+ if(ci!=null && ci.hasNext()) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ while(li.hasNext()) {
|
|
|
+ begin += csize;
|
|
|
+ List<T> list = li.next();
|
|
|
+ csize = list.size();
|
|
|
+ if(csize>0) {
|
|
|
+ ci = list.listIterator();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ci = null;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public T next() {
|
|
|
+ if(!hasNext()) {
|
|
|
+ throw new NoSuchElementException();
|
|
|
+ }
|
|
|
+ return ci.next();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int nextIndex() {
|
|
|
+ return ci!=null ? begin + ci.nextIndex() : 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean hasPrevious() {
|
|
|
+ if(ci!=null && ci.hasPrevious()) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ while(li.hasPrevious()) {
|
|
|
+ begin -= csize;
|
|
|
+ List<T> list = li.previous();
|
|
|
+ csize = list.size();
|
|
|
+ if(csize > 0) {
|
|
|
+ ci = list.listIterator();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ci = null;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public T previous() {
|
|
|
+ if(!hasPrevious()) {
|
|
|
+ throw new NoSuchElementException();
|
|
|
+ }
|
|
|
+ return ci.previous();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int previousIndex() {
|
|
|
+ return ci!=null ? begin + ci.previousIndex() : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void remove() {
|
|
|
+ if(ci==null) {
|
|
|
+ throw new IllegalStateException();
|
|
|
+ }
|
|
|
+ ci.remove();
|
|
|
+ csize--;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void set(T e) {
|
|
|
+ if(ci==null) {
|
|
|
+ throw new IllegalStateException();
|
|
|
+ }
|
|
|
+ ci.set(e);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void add(T e) {
|
|
|
+ if(ci==null && !hasNext()) {
|
|
|
+ throw new IllegalStateException("JoinList must contain at least one list if you want to add elements");
|
|
|
+ }
|
|
|
+ ci.add(e);
|
|
|
+ csize++;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|