src/share/classes/java/util/ArrayList.java

Print this page
rev 7046 : 4802647: Throw required NPEs from removeAll()/retainAll()
Reviewed-by: mduigou, chegar, dholmes
Contributed-by: Brandon Passanisi <brandon.passanisi@oracle.com>


 654     private String outOfBoundsMsg(int index) {
 655         return "Index: "+index+", Size: "+size;
 656     }
 657 
 658     /**
 659      * Removes from this list all of its elements that are contained in the
 660      * specified collection.
 661      *
 662      * @param c collection containing elements to be removed from this list
 663      * @return {@code true} if this list changed as a result of the call
 664      * @throws ClassCastException if the class of an element of this list
 665      *         is incompatible with the specified collection
 666      * (<a href="Collection.html#optional-restrictions">optional</a>)
 667      * @throws NullPointerException if this list contains a null element and the
 668      *         specified collection does not permit null elements
 669      * (<a href="Collection.html#optional-restrictions">optional</a>),
 670      *         or if the specified collection is null
 671      * @see Collection#contains(Object)
 672      */
 673     public boolean removeAll(Collection<?> c) {

 674         return batchRemove(c, false);
 675     }
 676 
 677     /**
 678      * Retains only the elements in this list that are contained in the
 679      * specified collection.  In other words, removes from this list all
 680      * of its elements that are not contained in the specified collection.
 681      *
 682      * @param c collection containing elements to be retained in this list
 683      * @return {@code true} if this list changed as a result of the call
 684      * @throws ClassCastException if the class of an element of this list
 685      *         is incompatible with the specified collection
 686      * (<a href="Collection.html#optional-restrictions">optional</a>)
 687      * @throws NullPointerException if this list contains a null element and the
 688      *         specified collection does not permit null elements
 689      * (<a href="Collection.html#optional-restrictions">optional</a>),
 690      *         or if the specified collection is null
 691      * @see Collection#contains(Object)
 692      */
 693     public boolean retainAll(Collection<?> c) {

 694         return batchRemove(c, true);
 695     }
 696 
 697     private boolean batchRemove(Collection<?> c, boolean complement) {
 698         final Object[] elementData = this.elementData;
 699         int r = 0, w = 0;
 700         boolean modified = false;
 701         try {
 702             for (; r < size; r++)
 703                 if (c.contains(elementData[r]) == complement)
 704                     elementData[w++] = elementData[r];
 705         } finally {
 706             // Preserve behavioral compatibility with AbstractCollection,
 707             // even if c.contains() throws.
 708             if (r != size) {
 709                 System.arraycopy(elementData, r,
 710                                  elementData, w,
 711                                  size - r);
 712                 w += size - r;
 713             }




 654     private String outOfBoundsMsg(int index) {
 655         return "Index: "+index+", Size: "+size;
 656     }
 657 
 658     /**
 659      * Removes from this list all of its elements that are contained in the
 660      * specified collection.
 661      *
 662      * @param c collection containing elements to be removed from this list
 663      * @return {@code true} if this list changed as a result of the call
 664      * @throws ClassCastException if the class of an element of this list
 665      *         is incompatible with the specified collection
 666      * (<a href="Collection.html#optional-restrictions">optional</a>)
 667      * @throws NullPointerException if this list contains a null element and the
 668      *         specified collection does not permit null elements
 669      * (<a href="Collection.html#optional-restrictions">optional</a>),
 670      *         or if the specified collection is null
 671      * @see Collection#contains(Object)
 672      */
 673     public boolean removeAll(Collection<?> c) {
 674         Objects.requireNonNull(c);
 675         return batchRemove(c, false);
 676     }
 677 
 678     /**
 679      * Retains only the elements in this list that are contained in the
 680      * specified collection.  In other words, removes from this list all
 681      * of its elements that are not contained in the specified collection.
 682      *
 683      * @param c collection containing elements to be retained in this list
 684      * @return {@code true} if this list changed as a result of the call
 685      * @throws ClassCastException if the class of an element of this list
 686      *         is incompatible with the specified collection
 687      * (<a href="Collection.html#optional-restrictions">optional</a>)
 688      * @throws NullPointerException if this list contains a null element and the
 689      *         specified collection does not permit null elements
 690      * (<a href="Collection.html#optional-restrictions">optional</a>),
 691      *         or if the specified collection is null
 692      * @see Collection#contains(Object)
 693      */
 694     public boolean retainAll(Collection<?> c) {
 695         Objects.requireNonNull(c);
 696         return batchRemove(c, true);
 697     }
 698 
 699     private boolean batchRemove(Collection<?> c, boolean complement) {
 700         final Object[] elementData = this.elementData;
 701         int r = 0, w = 0;
 702         boolean modified = false;
 703         try {
 704             for (; r < size; r++)
 705                 if (c.contains(elementData[r]) == complement)
 706                     elementData[w++] = elementData[r];
 707         } finally {
 708             // Preserve behavioral compatibility with AbstractCollection,
 709             // even if c.contains() throws.
 710             if (r != size) {
 711                 System.arraycopy(elementData, r,
 712                                  elementData, w,
 713                                  size - r);
 714                 w += size - r;
 715             }