1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.grouplens.grapht.util;
21
22 import com.google.common.collect.Iterators;
23
24 import javax.annotation.Nonnull;
25 import java.io.Serializable;
26 import java.util.AbstractList;
27 import java.util.Iterator;
28 import java.util.NoSuchElementException;
29
30
31
32
33
34
35
36 public abstract class AbstractChain<E extends Serializable> extends AbstractList<E> implements Serializable {
37 private static final long serialVersionUID = 1L;
38
39 protected final AbstractChain<E> previous;
40 protected final E tailValue;
41 protected final int length;
42
43
44
45
46
47
48 protected AbstractChain(AbstractChain<E> prev, E tv) {
49 previous = prev;
50 tailValue = tv;
51 if (prev == null) {
52 length = 1;
53 } else {
54 length = prev.length + 1;
55 }
56 }
57
58 public E getTailValue() {
59 return tailValue;
60 }
61
62 @Override
63 public int size() {
64 return length;
65 }
66
67 @Override
68 public E get(int i) {
69 com.google.common.base.Preconditions.checkElementIndex(i, length);
70 if (i == length - 1) {
71 return tailValue;
72 } else {
73 assert previous != null;
74 return previous.get(i);
75 }
76 }
77
78 @Nonnull
79 @Override
80 public Iterator<E> iterator() {
81 Iterator<E> current = Iterators.singletonIterator(tailValue);
82 if (previous == null) {
83 return current;
84 } else {
85 return Iterators.concat(previous.iterator(), current);
86 }
87 }
88
89
90
91
92
93 public Iterator<E> reverseIterator() {
94 return new Iterator<E>() {
95 AbstractChain<E> cur = AbstractChain.this;
96 @Override
97 public boolean hasNext() {
98 return cur != null;
99 }
100
101 @Override
102 public E next() {
103 if (cur == null) {
104 throw new NoSuchElementException();
105 }
106 E d = cur.tailValue;
107 cur = cur.previous;
108 return d;
109 }
110
111 @Override
112 public void remove() {
113 throw new UnsupportedOperationException();
114 }
115 };
116 }
117
118 public Iterable<E> reverse() {
119 return new Iterable<E>() {
120 @Override
121 public Iterator<E> iterator() {
122 return reverseIterator();
123 }
124 };
125 }
126
127 @Override
128 public int hashCode() {
129
130 return super.hashCode();
131 }
132
133 @Override
134 public boolean equals(Object o) {
135 if (o == this) {
136 return true;
137 } else if (o instanceof AbstractChain) {
138
139 return Iterators.elementsEqual(reverseIterator(),
140 ((AbstractChain) o).reverseIterator());
141 } else {
142 return super.equals(o);
143 }
144 }
145 }