1 /* 2 * Copyright 2001-2010 Stephen Colebourne 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package org.joda.primitives.collection.impl; 17 18 import java.lang.reflect.Array; 19 import java.util.Collection; 20 import java.util.Iterator; 21 22 import org.joda.primitives.DoubleUtils; 23 import org.joda.primitives.collection.DoubleCollection; 24 import org.joda.primitives.iterator.DoubleIterator; 25 26 /** 27 * Abstract base class for collections of primitive <code>double</code> elements. 28 * <p> 29 * This class implements {@link java.util.Collection Collection} allowing 30 * seamless integration with other APIs. 31 * <p> 32 * The <code>iterator</code> and <code>size</code> must be implemented by subclases. 33 * To make the subclass modifiable, the <code>add(double)</code> and 34 * iterator <code>remove()</code> methods must also be implemented. 35 * Subclasses may override other methods to increase efficiency. 36 * 37 * @author Stephen Colebourne 38 * @author Jason Tiscione 39 * @version CODE GENERATED 40 * @since 1.0 41 */ 42 public abstract class AbstractDoubleCollection 43 extends AbstractPrimitiveCollectable<Double> 44 implements DoubleCollection { 45 // This file is CODE GENERATED. Do not change manually. 46 47 /** 48 * Constructor. 49 */ 50 protected AbstractDoubleCollection() { 51 super(); 52 } 53 54 // Mandatory operations 55 //----------------------------------------------------------------------- 56 /** 57 * Checks whether this collection contains a specified primitive value. 58 * <p> 59 * This implementation uses <code>doubleIterator()</code>. 60 * 61 * @param value the value to search for 62 * @return <code>true</code> if the value is found 63 */ 64 public boolean contains(double value) { 65 for (DoubleIterator it = iterator(); it.hasNext();) { 66 if (it.nextDouble() == value) { 67 return true; 68 } 69 } 70 return false; 71 } 72 73 /** 74 * Checks if this collection contains all of the values in the specified array. 75 * If the specified array is empty, <code>true</code> is returned. 76 * <p> 77 * This implementation uses <code>contains(double)</code>. 78 * 79 * @param values the values to search for, null treated as empty array 80 * @return <code>true</code> if all of the values are found 81 */ 82 public boolean containsAll(double[] values) { 83 if (values != null) { 84 for (int i = 0; i < values.length; i++) { 85 if (contains(values[i]) == false) { 86 return false; 87 } 88 } 89 } 90 return true; 91 } 92 93 /** 94 * Checks if this collection contains all of the values in the specified collection. 95 * If the specified collection is empty, <code>true</code> is returned. 96 * <p> 97 * This implementation uses <code>contains(double)</code>. 98 * 99 * @param values the values to search for, null treated as empty collection 100 * @return <code>true</code> if all of the values are found 101 */ 102 public boolean containsAll(DoubleCollection values) { 103 if (values != null) { 104 for (DoubleIterator it = values.iterator(); it.hasNext(); ) { 105 if (contains(it.nextDouble()) == false) { 106 return false; 107 } 108 } 109 } 110 return true; 111 } 112 113 /** 114 * Checks if this collection contains any of the values in the specified array. 115 * If the specified array is empty, <code>false</code> is returned. 116 * <p> 117 * This implementation uses <code>contains(double)</code>. 118 * 119 * @param values the values to search for, null treated as empty array 120 * @return <code>true</code> if at least one of the values is found 121 */ 122 public boolean containsAny(double[] values) { 123 if (values != null) { 124 for (int i = 0; i < values.length; i++) { 125 if (contains(values[i])) { 126 return true; 127 } 128 } 129 } 130 return false; 131 } 132 133 /** 134 * Checks if this collection contains any of the values in the specified collection. 135 * If the specified collection is empty, <code>false</code> is returned. 136 * <p> 137 * This implementation uses <code>contains(double)</code>. 138 * 139 * @param values the values to search for, null treated as empty collection 140 * @return <code>true</code> if at least one of the values is found 141 */ 142 public boolean containsAny(DoubleCollection values) { 143 if (values != null) { 144 for (DoubleIterator it = values.iterator(); it.hasNext(); ) { 145 if (contains(it.nextDouble())) { 146 return true; 147 } 148 } 149 } 150 return false; 151 } 152 153 /** 154 * Gets the elements of this collection as an array. 155 * <p> 156 * This implementation uses <code>arrayCopy</code>. 157 * 158 * @return a new array containing a copy of the elements of this collection 159 */ 160 public double[] toDoubleArray() { 161 if (size() == 0) { 162 return DoubleUtils.EMPTY_DOUBLE_ARRAY; 163 } 164 double[] result = new double[size()]; 165 arrayCopy(0, result, 0, size()); 166 return result; 167 } 168 169 /** 170 * Copies the elements of this collection into an array at a specified position. 171 * Previous values in the array are overwritten. 172 * <p> 173 * If the array specified is null a new array is created. 174 * If the array specified is large enough, it will be modified. 175 * If the array is not large enough, a new array will be created containing the 176 * values from the specified array before the startIndex plus those from this collection. 177 * <p> 178 * This implementation uses <code>arrayCopy</code>. 179 * 180 * @param array the array to add the elements to, null treated as empty array 181 * @param startIndex the position in the array to start setting elements 182 * @return the array with the populated collection 183 * @throws IndexOutOfBoundsException if the index is negative 184 */ 185 public double[] toDoubleArray(double[] array, int startIndex) { 186 if (startIndex < 0) { 187 throw new IndexOutOfBoundsException("Start index must not be negative: " + startIndex); 188 } 189 double[] result = null; 190 if (array == null) { 191 // create new 192 result = new double[startIndex + size()]; 193 194 } else if (array.length - startIndex - size() >= 0) { 195 // room to fit data 196 result = array; 197 198 } else { 199 // expand array 200 result = new double[startIndex + size()]; 201 System.arraycopy(array, 0, result, 0, startIndex); 202 } 203 arrayCopy(0, result, startIndex, size()); 204 return result; 205 } 206 207 // Optional operations 208 //----------------------------------------------------------------------- 209 /** 210 * Clears the collection/map of all elements (optional operation). 211 * <p> 212 * The collection/map will have a zero size after this method completes. 213 * This method is optional, throwing an UnsupportedOperationException if the 214 * collection/map cannot be cleared. 215 * <p> 216 * This implementation uses <code>iterator()</code>. 217 * 218 * @throws UnsupportedOperationException if method not supported by this collection 219 */ 220 public void clear() { 221 checkRemoveModifiable(); 222 for (DoubleIterator it = iterator(); it.hasNext();) { 223 it.nextDouble(); 224 it.remove(); 225 } 226 } 227 228 /** 229 * Adds a primitive value to this collection (optional operation). 230 * <p> 231 * This implementation throws UnsupportedOperationException. 232 * 233 * @param value the value to add to this collection 234 * @return <code>true</code> if this collection was modified by this method call 235 * @throws IllegalArgumentException if value is rejected by this collection 236 * @throws UnsupportedOperationException if not supported by this collection 237 */ 238 public boolean add(double value) { 239 throw new UnsupportedOperationException("Collection does not support add"); 240 } 241 242 /** 243 * Adds an array of primitive values to this collection (optional operation). 244 * <p> 245 * This implementation uses <code>add(double)</code>. 246 * 247 * @param values the values to add to this collection, null treated as empty array 248 * @return <code>true</code> if this collection was modified by this method call 249 * @throws IllegalArgumentException if a value is rejected by this collection 250 * @throws UnsupportedOperationException if not supported by this collection 251 */ 252 public boolean addAll(double[] values) { 253 checkAddModifiable(); 254 boolean changed = false; 255 if (values != null) { 256 for (int i = 0; i < values.length; i++) { 257 changed |= add(values[i]); 258 } 259 } 260 return changed; 261 } 262 263 /** 264 * Adds a collection of primitive values to this collection (optional operation). 265 * <p> 266 * This implementation uses <code>add(double)</code>. 267 * 268 * @param values the values to add to this collection, null treated as empty collection 269 * @return <code>true</code> if this collection was modified by this method call 270 * @throws IllegalArgumentException if a value is rejected by this collection 271 * @throws UnsupportedOperationException if not supported by this collection 272 */ 273 public boolean addAll(DoubleCollection values) { 274 checkAddModifiable(); 275 boolean changed = false; 276 if (values != null) { 277 for (DoubleIterator it = values.iterator(); it.hasNext(); ) { 278 changed |= add(it.nextDouble()); 279 } 280 } 281 return changed; 282 } 283 284 /** 285 * Removes the first occurrence of the specified primitive value from this collection 286 * <p> 287 * This implementation uses <code>iterator().remove()</code>. 288 * 289 * @param value the value to remove 290 * @return <code>true</code> if this collection was modified by this method call 291 * @throws UnsupportedOperationException if not supported by this collection 292 */ 293 public boolean removeFirst(double value) { 294 checkRemoveModifiable(); 295 for (DoubleIterator it = iterator(); it.hasNext(); ) { 296 if (it.nextDouble() == value) { 297 it.remove(); 298 return true; 299 } 300 } 301 return false; 302 } 303 304 /** 305 * Removes all occurrences of the specified primitive value from this collection. 306 * <p> 307 * This implementation uses <code>iterator().remove()</code>. 308 * 309 * @param value the value to remove 310 * @return <code>true</code> if this collection was modified by this method call 311 * @throws UnsupportedOperationException if not supported by this collection 312 */ 313 public boolean removeAll(double value) { 314 checkRemoveModifiable(); 315 boolean changed = false; 316 for (DoubleIterator it = iterator(); it.hasNext(); ) { 317 if (it.nextDouble() == value) { 318 it.remove(); 319 changed = true; 320 } 321 } 322 return changed; 323 } 324 325 /** 326 * Removes all occurrences from this collection of each primitive in the specified array. 327 * <p> 328 * This implementation uses <code>iterator().remove()</code>. 329 * 330 * @param values the values to remove from this collection, null treated as empty array 331 * @return <code>true</code> if this list was modified by this method call 332 * @throws UnsupportedOperationException if not supported by this collection 333 */ 334 public boolean removeAll(double[] values) { 335 checkRemoveModifiable(); 336 boolean changed = false; 337 if (values != null) { 338 for (DoubleIterator it = iterator(); it.hasNext(); ) { 339 double value = it.nextDouble(); 340 for (int i = 0; i < values.length; i++) { 341 if (values[i] == value) { 342 it.remove(); 343 changed = true; 344 } 345 } 346 } 347 } 348 return changed; 349 } 350 351 /** 352 * Removes all occurrences from this collection of each primitive in the specified collection. 353 * <p> 354 * This implementation uses <code>iterator().remove()</code>. 355 * 356 * @param values the values to remove from this collection, null treated as empty collection 357 * @return <code>true</code> if this list was modified by this method call 358 * @throws UnsupportedOperationException if not supported by this collection 359 */ 360 public boolean removeAll(DoubleCollection values) { 361 checkRemoveModifiable(); 362 boolean changed = false; 363 if (values != null) { 364 for (DoubleIterator it = iterator(); it.hasNext(); ) { 365 if (values.contains(it.nextDouble())) { 366 it.remove(); 367 changed = true; 368 } 369 } 370 } 371 return changed; 372 } 373 374 /** 375 * Retains each element of this collection that is present in the specified array 376 * removing all other values. 377 * <p> 378 * This implementation uses <code>iterator().remove()</code>. 379 * 380 * @param values the values to remove from this collection, null treated as empty array 381 * @return <code>true</code> if this list was modified by this method call 382 * @throws UnsupportedOperationException if not supported by this collection 383 */ 384 public boolean retainAll(double[] values) { 385 checkRemoveModifiable(); 386 boolean changed = false; 387 if (values == null || values.length == 0) { 388 changed = !isEmpty(); 389 clear(); 390 } else { 391 for (DoubleIterator it = iterator(); it.hasNext(); ) { 392 double next = it.nextDouble(); 393 boolean match = false; 394 for (int i = 0; i < values.length; i++) { 395 if (values[i] == next) { 396 match = true; 397 break; 398 } 399 } 400 if (match == false) { 401 it.remove(); 402 changed = true; 403 } 404 } 405 } 406 return changed; 407 } 408 409 /** 410 * Retains each element of this collection that is present in the specified collection 411 * removing all other values. 412 * <p> 413 * This implementation uses <code>iterator().remove()</code>. 414 * 415 * @param values the values to retain in this collection, null treated as empty collection 416 * @return <code>true</code> if this collection was modified by this method call 417 * @throws UnsupportedOperationException if not supported by this collection 418 */ 419 public boolean retainAll(DoubleCollection values) { 420 checkRemoveModifiable(); 421 boolean changed = false; 422 if (values == null || values.isEmpty()) { 423 changed = !isEmpty(); 424 clear(); 425 } else { 426 for (DoubleIterator it = iterator(); it.hasNext(); ) { 427 if (values.contains(it.nextDouble()) == false) { 428 it.remove(); 429 changed = true; 430 } 431 } 432 } 433 return changed; 434 } 435 436 // Collection integration 437 //----------------------------------------------------------------------- 438 /** 439 * Checks whether this collection contains a specified <code>Double</code> value. 440 * <p> 441 * This implementation uses <code>contains(double)</code>. 442 * 443 * @param value the value to search for 444 * @return <code>true</code> if the value is found 445 */ 446 public boolean contains(Object value) { 447 return contains(toPrimitive(value)); 448 } 449 450 /** 451 * Checks if the collection contains all of the primitive values. 452 * <p> 453 * This implementation uses <code>containsAll(double[])</code>. 454 * 455 * @param coll the collection of values to search for 456 * @return <code>true</code> if all the values are found 457 */ 458 public boolean containsAll(Collection<?> coll) { 459 if (coll == this || coll.size() == 0) { 460 return true; 461 } 462 if (size() == 0) { 463 return false; 464 } 465 return containsAll(toPrimitiveArray(coll)); 466 } 467 468 /** 469 * Checks if the collection contains any of the primitive values in the array. 470 * If the specified collection is empty, <code>false</code> is returned. 471 * <p> 472 * This implementation uses <code>containsAny(double[])</code>. 473 * 474 * @param coll the collection of values to search for 475 * @return <code>true</code> if at least one of the values is found 476 */ 477 public boolean containsAny(Collection<?> coll) { 478 if (size() == 0 || coll.size() == 0) { 479 return false; 480 } 481 if (coll == this) { 482 return true; 483 } 484 return containsAny(toPrimitiveArray(coll)); 485 } 486 487 /** 488 * Gets the collection as an array of <code>Double</code>. 489 * 490 * @return an array of <code>Double</code> 491 */ 492 public Object[] toArray() { 493 Object[] result = new Double[size()]; 494 DoubleIterator it = iterator(); 495 for (int i = 0; it.hasNext(); i++) { 496 result[i] = it.next(); 497 } 498 return result; 499 } 500 501 /** 502 * Gets the collection as an array, using the array provided. 503 * 504 * @param array the array to populate 505 * @return an array of <code>Double</code> 506 */ 507 @SuppressWarnings("unchecked") 508 public <T> T[] toArray(T[] array) { 509 int size = size(); 510 if (array.length < size) { 511 array = (T[]) Array.newInstance(array.getClass().getComponentType(), size); 512 } 513 514 Iterator<Double> it = iterator(); 515 for (int i = 0; i < size; i++) { 516 array[i] = (T)it.next(); 517 } 518 519 if (array.length > size) { 520 array[size] = null; 521 } 522 523 return array; 524 } 525 526 /** 527 * Adds the <code>Double</code> value to this collection (optional operation). 528 * <p> 529 * This method is optional, throwing an UnsupportedOperationException if the 530 * collection cannot be added to. 531 * <p> 532 * This implementation uses <code>add(double)</code>. 533 * 534 * @param value the value to add to this collection 535 * @return <code>true</code> if this collection was modified by this method call 536 * @throws IllegalArgumentException if value is rejected by this collection 537 * @throws UnsupportedOperationException if not supported by this collection 538 */ 539 public boolean add(Double value) { 540 checkAddModifiable(); 541 return add(toPrimitive(value)); 542 } 543 544 /** 545 * Adds a collection of <code>Double</code> values to this collection (optional operation). 546 * <p> 547 * This method is optional, throwing an UnsupportedOperationException if the 548 * collection cannot be added to. 549 * <p> 550 * This implementation uses <code>addAll(double[])</code>. 551 * 552 * @param coll the values to add to this collection 553 * @return <code>true</code> if this list was modified by this method call 554 * @throws IndexOutOfBoundsException if the index is invalid 555 * @throws ClassCastException if any object is not <code>Double</code> 556 * @throws IllegalArgumentException if value is rejected by this collection 557 * @throws UnsupportedOperationException if not supported by this collection 558 */ 559 public boolean addAll(Collection<? extends Double> coll) { 560 checkAddModifiable(); 561 return addAll(toPrimitiveArray(coll)); 562 } 563 564 /** 565 * Removes the first occurrance of the specified <code>Double</code> value from 566 * this collection (optional operation). 567 * <p> 568 * This method is optional, throwing an UnsupportedOperationException if the 569 * collection cannot be removed from. 570 * <p> 571 * This implementation uses <code>removeFirst(double)</code>. 572 * 573 * @param value the value to remove 574 * @return <code>true</code> if this collection was modified by this method call 575 * @throws UnsupportedOperationException if not supported by this collection 576 */ 577 public boolean remove(Object value) { 578 checkRemoveModifiable(); 579 return removeFirst(toPrimitive(value)); 580 } 581 582 /** 583 * Removes each of a collection of <code>Double</code> values from this collection (optional operation). 584 * <p> 585 * This method is optional, throwing an UnsupportedOperationException if the 586 * collection cannot be added to. 587 * <p> 588 * This implementation uses <code>removeAll(double[])</code>. 589 * 590 * @param coll the values to remove from this collection 591 * @return <code>true</code> if this list was modified by this method call 592 * @throws UnsupportedOperationException if not supported by this collection 593 */ 594 public boolean removeAll(Collection<?> coll) { 595 checkRemoveModifiable(); 596 if (coll == this) { 597 int size = size(); 598 clear(); 599 return (size() != size); 600 } 601 return removeAll(toPrimitiveArray(coll)); 602 } 603 604 /** 605 * Retains each of a collection of <code>Double</code> values, removing other 606 * values (optional operation). 607 * <p> 608 * This method is optional, throwing an UnsupportedOperationException if the 609 * collection cannot be added to. 610 * <p> 611 * This implementation uses <code>retainAll(double[])</code>. 612 * 613 * @param coll the values to retain in this collection 614 * @return <code>true</code> if this list was modified by this method call 615 * @throws UnsupportedOperationException if not supported by this collection 616 */ 617 public boolean retainAll(Collection<?> coll) { 618 checkRemoveModifiable(); 619 if (coll == this) { 620 return false; 621 } 622 return retainAll(toPrimitiveArray(coll)); 623 } 624 625 // Basics 626 //----------------------------------------------------------------------- 627 /** 628 * Gets a string representing this collection. 629 * <p> 630 * The format used is as per <code>Collection</code>. 631 * 632 * @return collection as a String 633 */ 634 public String toString() { 635 StringBuffer buf = new StringBuffer(); 636 buf.append("["); 637 638 DoubleIterator it = iterator(); 639 boolean hasNext = it.hasNext(); 640 while (hasNext) { 641 buf.append(it.nextDouble()); 642 hasNext = it.hasNext(); 643 if (hasNext) { 644 buf.append(", "); 645 } 646 } 647 648 buf.append("]"); 649 return buf.toString(); 650 } 651 652 // Internals 653 //----------------------------------------------------------------------- 654 /** 655 * Copies data from this collection into the specified array. 656 * This method is pre-validated. 657 * 658 * @param fromIndex the index to start from 659 * @param dest the destination array 660 * @param destIndex the destination start index 661 * @param size the number of items to copy 662 */ 663 protected void arrayCopy(int fromIndex, double[] dest, int destIndex, int size) { 664 DoubleIterator it = iterator(); 665 for (int i = 0; it.hasNext() && i < size; i++) { 666 dest[destIndex + i] = it.nextDouble(); 667 } 668 } 669 670 /** 671 * Are the add methods supported. 672 * <p> 673 * This implementation returns false. 674 * 675 * @return true if supported 676 */ 677 protected boolean isAddModifiable() { 678 return false; 679 } 680 681 /** 682 * Are the remove methods supported. 683 * <p> 684 * This implementation returns false. 685 * 686 * @return true if supported 687 */ 688 protected boolean isRemoveModifiable() { 689 return false; 690 } 691 692 /** 693 * Is the collection modifiable in any way. 694 * 695 * @return true if supported 696 */ 697 public boolean isModifiable() { 698 return isAddModifiable() || isRemoveModifiable(); 699 } 700 701 /** 702 * Check whether add is suported and throw an exception. 703 */ 704 protected void checkAddModifiable() { 705 if (isAddModifiable() == false) { 706 throw new UnsupportedOperationException("Collection does not support add"); 707 } 708 } 709 710 /** 711 * Check whether remove is suported and throw an exception. 712 */ 713 protected void checkRemoveModifiable() { 714 if (isRemoveModifiable() == false) { 715 throw new UnsupportedOperationException("Collection does not support remove"); 716 } 717 } 718 719 /** 720 * Wraps an <code>double</code> with an Object wrapper. 721 * 722 * @param value the primitive value 723 * @return the Object wrapper 724 */ 725 protected Double toObject(double value) { 726 return DoubleUtils.toObject(value); 727 } 728 729 /** 730 * Checks if the object can be converted to a primitive successfully. 731 * <p> 732 * This implementation only allows non-null Double objects. 733 * 734 * @param value the Object wrapper 735 * @return true if a primitive value can be successfully extracted 736 */ 737 protected boolean isToPrimitivePossible(Object value) { 738 return (value instanceof Double); 739 } 740 741 /** 742 * Unwraps the <code>Double</code> to retrieve the primitive <code>double</code>. 743 * <p> 744 * This implementation only allows non-null Double objects. 745 * 746 * @param value the Object to convert to a primitive 747 * @return the primitive value 748 * @throws NullPointerException if the value is null and this is unacceptable 749 * @throws ClassCastException if the object is of an unsuitable type 750 */ 751 protected double toPrimitive(Object value) { 752 return DoubleUtils.toPrimitive(value); 753 } 754 755 /** 756 * Unwraps a <code>Collection</code> to retrieve the primitive <code>double</code>. 757 * <p> 758 * This implementation only allows non-null Double objects. 759 * 760 * @param coll the Collection to convert to primitives 761 * @return the primitive value 762 * @throws NullPointerException if the value is null and this is unacceptable 763 * @throws ClassCastException if any object is of an unsuitable type 764 */ 765 protected double[] toPrimitiveArray(Collection<?> coll) { 766 return DoubleUtils.toPrimitiveArray(coll); 767 } 768 769 }