1. /*
  2. * $Header: /home/cvs/jakarta-commons/primitives/src/java/org/apache/commons/collections/primitives/RandomAccessDoubleList.java,v 1.3 2003/10/16 20:49:36 scolebourne Exp $
  3. * ====================================================================
  4. * The Apache Software License, Version 1.1
  5. *
  6. * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
  7. * reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. *
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. *
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in
  18. * the documentation and/or other materials provided with the
  19. * distribution.
  20. *
  21. * 3. The end-user documentation included with the redistribution, if
  22. * any, must include the following acknowledgement:
  23. * "This product includes software developed by the
  24. * Apache Software Foundation (http://www.apache.org/)."
  25. * Alternately, this acknowledgement may appear in the software itself,
  26. * if and wherever such third-party acknowledgements normally appear.
  27. *
  28. * 4. The names "The Jakarta Project", "Commons", and "Apache Software
  29. * Foundation" must not be used to endorse or promote products derived
  30. * from this software without prior written permission. For written
  31. * permission, please contact apache@apache.org.
  32. *
  33. * 5. Products derived from this software may not be called "Apache"
  34. * nor may "Apache" appear in their names without prior written
  35. * permission of the Apache Software Foundation.
  36. *
  37. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  38. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  39. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  40. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  41. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  42. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  43. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  44. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  45. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  46. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  47. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  48. * SUCH DAMAGE.
  49. * ====================================================================
  50. *
  51. * This software consists of voluntary contributions made by many
  52. * individuals on behalf of the Apache Software Foundation. For more
  53. * information on the Apache Software Foundation, please see
  54. * <http://www.apache.org/>.
  55. *
  56. */
  57. package org.apache.commons.collections.primitives;
  58. import java.util.ConcurrentModificationException;
  59. import java.util.NoSuchElementException;
  60. /**
  61. * Abstract base class for {@link DoubleList}s backed
  62. * by random access structures like arrays.
  63. * <p />
  64. * Read-only subclasses must override {@link #get}
  65. * and {@link #size}. Mutable subclasses
  66. * should also override {@link #set}. Variably-sized
  67. * subclasses should also override {@link #add}
  68. * and {@link #removeElementAt}. All other methods
  69. * have at least some base implementation derived from
  70. * these. Subclasses may choose to override these methods
  71. * to provide a more efficient implementation.
  72. *
  73. * @since Commons Primitives 1.0
  74. * @version $Revision: 1.3 $ $Date: 2003/10/16 20:49:36 $
  75. *
  76. * @author Rodney Waldhoff
  77. */
  78. public abstract class RandomAccessDoubleList extends AbstractDoubleCollection implements DoubleList {
  79. // constructors
  80. //-------------------------------------------------------------------------
  81. /** Constructs an empty list. */
  82. protected RandomAccessDoubleList() {
  83. }
  84. // fully abstract methods
  85. //-------------------------------------------------------------------------
  86. public abstract double get(int index);
  87. public abstract int size();
  88. // unsupported in base
  89. //-------------------------------------------------------------------------
  90. /**
  91. * Unsupported in this implementation.
  92. * @throws UnsupportedOperationException since this method is not supported
  93. */
  94. public double removeElementAt(int index) {
  95. throw new UnsupportedOperationException();
  96. }
  97. /**
  98. * Unsupported in this implementation.
  99. * @throws UnsupportedOperationException since this method is not supported
  100. */
  101. public double set(int index, double element) {
  102. throw new UnsupportedOperationException();
  103. }
  104. /**
  105. * Unsupported in this implementation.
  106. * @throws UnsupportedOperationException since this method is not supported
  107. */
  108. public void add(int index, double element) {
  109. throw new UnsupportedOperationException();
  110. }
  111. //-------------------------------------------------------------------------
  112. // javadocs here are inherited
  113. public boolean add(double element) {
  114. add(size(),element);
  115. return true;
  116. }
  117. public boolean addAll(int index, DoubleCollection collection) {
  118. boolean modified = false;
  119. for(DoubleIterator iter = collection.iterator(); iter.hasNext(); ) {
  120. add(index++,iter.next());
  121. modified = true;
  122. }
  123. return modified;
  124. }
  125. public int indexOf(double element) {
  126. int i = 0;
  127. for(DoubleIterator iter = iterator(); iter.hasNext(); ) {
  128. if(iter.next() == element) {
  129. return i;
  130. } else {
  131. i++;
  132. }
  133. }
  134. return -1;
  135. }
  136. public int lastIndexOf(double element) {
  137. for(DoubleListIterator iter = listIterator(size()); iter.hasPrevious(); ) {
  138. if(iter.previous() == element) {
  139. return iter.nextIndex();
  140. }
  141. }
  142. return -1;
  143. }
  144. public DoubleIterator iterator() {
  145. return listIterator();
  146. }
  147. public DoubleListIterator listIterator() {
  148. return listIterator(0);
  149. }
  150. public DoubleListIterator listIterator(int index) {
  151. return new RandomAccessDoubleListIterator(this,index);
  152. }
  153. public DoubleList subList(int fromIndex, int toIndex) {
  154. return new RandomAccessDoubleSubList(this,fromIndex,toIndex);
  155. }
  156. public boolean equals(Object that) {
  157. if(this == that) {
  158. return true;
  159. } else if(that instanceof DoubleList) {
  160. DoubleList thatList = (DoubleList)that;
  161. if(size() != thatList.size()) {
  162. return false;
  163. }
  164. for(DoubleIterator thatIter = thatList.iterator(), thisIter = iterator(); thisIter.hasNext();) {
  165. if(thisIter.next() != thatIter.next()) {
  166. return false;
  167. }
  168. }
  169. return true;
  170. } else {
  171. return false;
  172. }
  173. }
  174. public int hashCode() {
  175. int hash = 1;
  176. for(DoubleIterator iter = iterator(); iter.hasNext(); ) {
  177. long bits = Double.doubleToLongBits(iter.next());
  178. hash = 31*hash + ((int)(bits ^ (bits >>> 32)));
  179. }
  180. return hash;
  181. }
  182. public String toString() {
  183. StringBuffer buf = new StringBuffer();
  184. buf.append("[");
  185. for(DoubleIterator iter = iterator(); iter.hasNext();) {
  186. buf.append(iter.next());
  187. if(iter.hasNext()) {
  188. buf.append(", ");
  189. }
  190. }
  191. buf.append("]");
  192. return buf.toString();
  193. }
  194. // protected utilities
  195. //-------------------------------------------------------------------------
  196. /** Get my count of structural modifications. */
  197. protected int getModCount() {
  198. return _modCount;
  199. }
  200. /** Increment my count of structural modifications. */
  201. protected void incrModCount() {
  202. _modCount++;
  203. }
  204. // attributes
  205. //-------------------------------------------------------------------------
  206. private int _modCount = 0;
  207. // inner classes
  208. //-------------------------------------------------------------------------
  209. private static class ComodChecker {
  210. ComodChecker(RandomAccessDoubleList source) {
  211. _source = source;
  212. resyncModCount();
  213. }
  214. protected RandomAccessDoubleList getList() {
  215. return _source;
  216. }
  217. protected void assertNotComodified() throws ConcurrentModificationException {
  218. if(_expectedModCount != getList().getModCount()) {
  219. throw new ConcurrentModificationException();
  220. }
  221. }
  222. protected void resyncModCount() {
  223. _expectedModCount = getList().getModCount();
  224. }
  225. private RandomAccessDoubleList _source = null;
  226. private int _expectedModCount = -1;
  227. }
  228. protected static class RandomAccessDoubleListIterator extends ComodChecker implements DoubleListIterator {
  229. RandomAccessDoubleListIterator(RandomAccessDoubleList list, int index) {
  230. super(list);
  231. if(index < 0 || index > getList().size()) {
  232. throw new IndexOutOfBoundsException("Index " + index + " not in [0," + getList().size() + ")");
  233. } else {
  234. _nextIndex = index;
  235. resyncModCount();
  236. }
  237. }
  238. public boolean hasNext() {
  239. assertNotComodified();
  240. return _nextIndex < getList().size();
  241. }
  242. public boolean hasPrevious() {
  243. assertNotComodified();
  244. return _nextIndex > 0;
  245. }
  246. public int nextIndex() {
  247. assertNotComodified();
  248. return _nextIndex;
  249. }
  250. public int previousIndex() {
  251. assertNotComodified();
  252. return _nextIndex - 1;
  253. }
  254. public double next() {
  255. assertNotComodified();
  256. if(!hasNext()) {
  257. throw new NoSuchElementException();
  258. } else {
  259. double val = getList().get(_nextIndex);
  260. _lastReturnedIndex = _nextIndex;
  261. _nextIndex++;
  262. return val;
  263. }
  264. }
  265. public double previous() {
  266. assertNotComodified();
  267. if(!hasPrevious()) {
  268. throw new NoSuchElementException();
  269. } else {
  270. double val = getList().get(_nextIndex-1);
  271. _lastReturnedIndex = _nextIndex-1;
  272. _nextIndex--;
  273. return val;
  274. }
  275. }
  276. public void add(double value) {
  277. assertNotComodified();
  278. getList().add(_nextIndex,value);
  279. _nextIndex++;
  280. _lastReturnedIndex = -1;
  281. resyncModCount();
  282. }
  283. public void remove() {
  284. assertNotComodified();
  285. if(-1 == _lastReturnedIndex) {
  286. throw new IllegalStateException();
  287. } else {
  288. getList().removeElementAt(_lastReturnedIndex);
  289. _lastReturnedIndex = -1;
  290. _nextIndex--;
  291. resyncModCount();
  292. }
  293. }
  294. public void set(double value) {
  295. assertNotComodified();
  296. if(-1 == _lastReturnedIndex) {
  297. throw new IllegalStateException();
  298. } else {
  299. getList().set(_lastReturnedIndex,value);
  300. resyncModCount();
  301. }
  302. }
  303. private int _nextIndex = 0;
  304. private int _lastReturnedIndex = -1;
  305. }
  306. protected static class RandomAccessDoubleSubList extends RandomAccessDoubleList implements DoubleList {
  307. RandomAccessDoubleSubList(RandomAccessDoubleList list, int fromIndex, int toIndex) {
  308. if(fromIndex < 0 || toIndex > list.size()) {
  309. throw new IndexOutOfBoundsException();
  310. } else if(fromIndex > toIndex) {
  311. throw new IllegalArgumentException();
  312. } else {
  313. _list = list;
  314. _offset = fromIndex;
  315. _limit = toIndex - fromIndex;
  316. _comod = new ComodChecker(list);
  317. _comod.resyncModCount();
  318. }
  319. }
  320. public double get(int index) {
  321. checkRange(index);
  322. _comod.assertNotComodified();
  323. return _list.get(toUnderlyingIndex(index));
  324. }
  325. public double removeElementAt(int index) {
  326. checkRange(index);
  327. _comod.assertNotComodified();
  328. double val = _list.removeElementAt(toUnderlyingIndex(index));
  329. _limit--;
  330. _comod.resyncModCount();
  331. incrModCount();
  332. return val;
  333. }
  334. public double set(int index, double element) {
  335. checkRange(index);
  336. _comod.assertNotComodified();
  337. double val = _list.set(toUnderlyingIndex(index),element);
  338. incrModCount();
  339. _comod.resyncModCount();
  340. return val;
  341. }
  342. public void add(int index, double element) {
  343. checkRangeIncludingEndpoint(index);
  344. _comod.assertNotComodified();
  345. _list.add(toUnderlyingIndex(index),element);
  346. _limit++;
  347. _comod.resyncModCount();
  348. incrModCount();
  349. }
  350. public int size() {
  351. _comod.assertNotComodified();
  352. return _limit;
  353. }
  354. private void checkRange(int index) {
  355. if(index < 0 || index >= size()) {
  356. throw new IndexOutOfBoundsException("index " + index + " not in [0," + size() + ")");
  357. }
  358. }
  359. private void checkRangeIncludingEndpoint(int index) {
  360. if(index < 0 || index > size()) {
  361. throw new IndexOutOfBoundsException("index " + index + " not in [0," + size() + "]");
  362. }
  363. }
  364. private int toUnderlyingIndex(int index) {
  365. return (index + _offset);
  366. }
  367. private int _offset = 0;
  368. private int _limit = 0;
  369. private RandomAccessDoubleList _list = null;
  370. private ComodChecker _comod = null;
  371. }
  372. }