< prev index next >

src/java.base/share/classes/java/util/Collections.java

Print this page
8205184: Delegating Iterator implementations that don't delegate forEachRemaining()
Reviewed-by: psandoz
Contributed-by: Tobias Thierer <tobiast@google.com>, Martin Buchholz <martinrb@google.com>


1552         }
1553 
1554         /**
1555          * We need this class in addition to UnmodifiableSet as
1556          * Map.Entries themselves permit modification of the backing Map
1557          * via their setValue operation.  This class is subtle: there are
1558          * many possible attacks that must be thwarted.
1559          *
1560          * @serial include
1561          */
1562         static class UnmodifiableEntrySet<K,V>
1563             extends UnmodifiableSet<Map.Entry<K,V>> {
1564             private static final long serialVersionUID = 7854390611657943733L;
1565 
1566             @SuppressWarnings({"unchecked", "rawtypes"})
1567             UnmodifiableEntrySet(Set<? extends Map.Entry<? extends K, ? extends V>> s) {
1568                 // Need to cast to raw in order to work around a limitation in the type system
1569                 super((Set)s);
1570             }
1571 
1572             static <K, V> Consumer<Map.Entry<K, V>> entryConsumer(Consumer<? super Entry<K, V>> action) {

1573                 return e -> action.accept(new UnmodifiableEntry<>(e));
1574             }
1575 
1576             public void forEach(Consumer<? super Entry<K, V>> action) {
1577                 Objects.requireNonNull(action);
1578                 c.forEach(entryConsumer(action));
1579             }
1580 
1581             static final class UnmodifiableEntrySetSpliterator<K, V>
1582                     implements Spliterator<Entry<K,V>> {
1583                 final Spliterator<Map.Entry<K, V>> s;
1584 
1585                 UnmodifiableEntrySetSpliterator(Spliterator<Entry<K, V>> s) {
1586                     this.s = s;
1587                 }
1588 
1589                 @Override
1590                 public boolean tryAdvance(Consumer<? super Entry<K, V>> action) {
1591                     Objects.requireNonNull(action);
1592                     return s.tryAdvance(entryConsumer(action));


1644             }
1645 
1646             @Override
1647             public Stream<Entry<K,V>> parallelStream() {
1648                 return StreamSupport.stream(spliterator(), true);
1649             }
1650 
1651             public Iterator<Map.Entry<K,V>> iterator() {
1652                 return new Iterator<Map.Entry<K,V>>() {
1653                     private final Iterator<? extends Map.Entry<? extends K, ? extends V>> i = c.iterator();
1654 
1655                     public boolean hasNext() {
1656                         return i.hasNext();
1657                     }
1658                     public Map.Entry<K,V> next() {
1659                         return new UnmodifiableEntry<>(i.next());
1660                     }
1661                     public void remove() {
1662                         throw new UnsupportedOperationException();
1663                     }



1664                 };
1665             }
1666 
1667             @SuppressWarnings("unchecked")
1668             public Object[] toArray() {
1669                 Object[] a = c.toArray();
1670                 for (int i=0; i<a.length; i++)
1671                     a[i] = new UnmodifiableEntry<>((Map.Entry<? extends K, ? extends V>)a[i]);
1672                 return a;
1673             }
1674 
1675             @SuppressWarnings("unchecked")
1676             public <T> T[] toArray(T[] a) {
1677                 // We don't pass a to c.toArray, to avoid window of
1678                 // vulnerability wherein an unscrupulous multithreaded client
1679                 // could get his hands on raw (unwrapped) Entries from c.
1680                 Object[] arr = c.toArray(a.length==0 ? a : Arrays.copyOf(a, 0));
1681 
1682                 for (int i=0; i<arr.length; i++)
1683                     arr[i] = new UnmodifiableEntry<>((Map.Entry<? extends K, ? extends V>)arr[i]);


3064         public boolean remove(Object o)            { return c.remove(o); }
3065         public void clear()                        {        c.clear(); }
3066 
3067         public boolean containsAll(Collection<?> coll) {
3068             return c.containsAll(coll);
3069         }
3070         public boolean removeAll(Collection<?> coll) {
3071             return c.removeAll(coll);
3072         }
3073         public boolean retainAll(Collection<?> coll) {
3074             return c.retainAll(coll);
3075         }
3076 
3077         public Iterator<E> iterator() {
3078             // JDK-6363904 - unwrapped iterator could be typecast to
3079             // ListIterator with unsafe set()
3080             final Iterator<E> it = c.iterator();
3081             return new Iterator<E>() {
3082                 public boolean hasNext() { return it.hasNext(); }
3083                 public E next()          { return it.next(); }
3084                 public void remove()     {        it.remove(); }};




3085         }
3086 
3087         public boolean add(E e)          { return c.add(typeCheck(e)); }
3088 
3089         private E[] zeroLengthElementArray; // Lazily initialized
3090 
3091         private E[] zeroLengthElementArray() {
3092             return zeroLengthElementArray != null ? zeroLengthElementArray :
3093                 (zeroLengthElementArray = zeroLengthArray(type));
3094         }
3095 
3096         @SuppressWarnings("unchecked")
3097         Collection<E> checkedCopyOf(Collection<? extends E> coll) {
3098             Object[] a;
3099             try {
3100                 E[] z = zeroLengthElementArray();
3101                 a = coll.toArray(z);
3102                 // Defend against coll violating the toArray contract
3103                 if (a.getClass() != z.getClass())
3104                     a = Arrays.copyOf(a, a.length, z.getClass());


3740             CheckedEntrySet(Set<Map.Entry<K, V>> s, Class<V> valueType) {
3741                 this.s = s;
3742                 this.valueType = valueType;
3743             }
3744 
3745             public int size()        { return s.size(); }
3746             public boolean isEmpty() { return s.isEmpty(); }
3747             public String toString() { return s.toString(); }
3748             public int hashCode()    { return s.hashCode(); }
3749             public void clear()      {        s.clear(); }
3750 
3751             public boolean add(Map.Entry<K, V> e) {
3752                 throw new UnsupportedOperationException();
3753             }
3754             public boolean addAll(Collection<? extends Map.Entry<K, V>> coll) {
3755                 throw new UnsupportedOperationException();
3756             }
3757 
3758             public Iterator<Map.Entry<K,V>> iterator() {
3759                 final Iterator<Map.Entry<K, V>> i = s.iterator();
3760                 final Class<V> valueType = this.valueType;
3761 
3762                 return new Iterator<Map.Entry<K,V>>() {
3763                     public boolean hasNext() { return i.hasNext(); }
3764                     public void remove()     { i.remove(); }
3765 
3766                     public Map.Entry<K,V> next() {
3767                         return checkedEntry(i.next(), valueType);





3768                     }
3769                 };
3770             }
3771 
3772             @SuppressWarnings("unchecked")
3773             public Object[] toArray() {
3774                 Object[] source = s.toArray();
3775 
3776                 /*
3777                  * Ensure that we don't get an ArrayStoreException even if
3778                  * s.toArray returns an array of something other than Object
3779                  */
3780                 Object[] dest = (source.getClass() == Object[].class)
3781                     ? source
3782                     : new Object[source.length];
3783 
3784                 for (int i = 0; i < source.length; i++)
3785                     dest[i] = checkedEntry((Map.Entry<K,V>)source[i],
3786                                            valueType);
3787                 return dest;




1552         }
1553 
1554         /**
1555          * We need this class in addition to UnmodifiableSet as
1556          * Map.Entries themselves permit modification of the backing Map
1557          * via their setValue operation.  This class is subtle: there are
1558          * many possible attacks that must be thwarted.
1559          *
1560          * @serial include
1561          */
1562         static class UnmodifiableEntrySet<K,V>
1563             extends UnmodifiableSet<Map.Entry<K,V>> {
1564             private static final long serialVersionUID = 7854390611657943733L;
1565 
1566             @SuppressWarnings({"unchecked", "rawtypes"})
1567             UnmodifiableEntrySet(Set<? extends Map.Entry<? extends K, ? extends V>> s) {
1568                 // Need to cast to raw in order to work around a limitation in the type system
1569                 super((Set)s);
1570             }
1571 
1572             static <K, V> Consumer<Map.Entry<? extends K, ? extends V>> entryConsumer(
1573                     Consumer<? super Entry<K, V>> action) {
1574                 return e -> action.accept(new UnmodifiableEntry<>(e));
1575             }
1576 
1577             public void forEach(Consumer<? super Entry<K, V>> action) {
1578                 Objects.requireNonNull(action);
1579                 c.forEach(entryConsumer(action));
1580             }
1581 
1582             static final class UnmodifiableEntrySetSpliterator<K, V>
1583                     implements Spliterator<Entry<K,V>> {
1584                 final Spliterator<Map.Entry<K, V>> s;
1585 
1586                 UnmodifiableEntrySetSpliterator(Spliterator<Entry<K, V>> s) {
1587                     this.s = s;
1588                 }
1589 
1590                 @Override
1591                 public boolean tryAdvance(Consumer<? super Entry<K, V>> action) {
1592                     Objects.requireNonNull(action);
1593                     return s.tryAdvance(entryConsumer(action));


1645             }
1646 
1647             @Override
1648             public Stream<Entry<K,V>> parallelStream() {
1649                 return StreamSupport.stream(spliterator(), true);
1650             }
1651 
1652             public Iterator<Map.Entry<K,V>> iterator() {
1653                 return new Iterator<Map.Entry<K,V>>() {
1654                     private final Iterator<? extends Map.Entry<? extends K, ? extends V>> i = c.iterator();
1655 
1656                     public boolean hasNext() {
1657                         return i.hasNext();
1658                     }
1659                     public Map.Entry<K,V> next() {
1660                         return new UnmodifiableEntry<>(i.next());
1661                     }
1662                     public void remove() {
1663                         throw new UnsupportedOperationException();
1664                     }
1665                     public void forEachRemaining(Consumer<? super Map.Entry<K, V>> action) {
1666                         i.forEachRemaining(entryConsumer(action));
1667                     }
1668                 };
1669             }
1670 
1671             @SuppressWarnings("unchecked")
1672             public Object[] toArray() {
1673                 Object[] a = c.toArray();
1674                 for (int i=0; i<a.length; i++)
1675                     a[i] = new UnmodifiableEntry<>((Map.Entry<? extends K, ? extends V>)a[i]);
1676                 return a;
1677             }
1678 
1679             @SuppressWarnings("unchecked")
1680             public <T> T[] toArray(T[] a) {
1681                 // We don't pass a to c.toArray, to avoid window of
1682                 // vulnerability wherein an unscrupulous multithreaded client
1683                 // could get his hands on raw (unwrapped) Entries from c.
1684                 Object[] arr = c.toArray(a.length==0 ? a : Arrays.copyOf(a, 0));
1685 
1686                 for (int i=0; i<arr.length; i++)
1687                     arr[i] = new UnmodifiableEntry<>((Map.Entry<? extends K, ? extends V>)arr[i]);


3068         public boolean remove(Object o)            { return c.remove(o); }
3069         public void clear()                        {        c.clear(); }
3070 
3071         public boolean containsAll(Collection<?> coll) {
3072             return c.containsAll(coll);
3073         }
3074         public boolean removeAll(Collection<?> coll) {
3075             return c.removeAll(coll);
3076         }
3077         public boolean retainAll(Collection<?> coll) {
3078             return c.retainAll(coll);
3079         }
3080 
3081         public Iterator<E> iterator() {
3082             // JDK-6363904 - unwrapped iterator could be typecast to
3083             // ListIterator with unsafe set()
3084             final Iterator<E> it = c.iterator();
3085             return new Iterator<E>() {
3086                 public boolean hasNext() { return it.hasNext(); }
3087                 public E next()          { return it.next(); }
3088                 public void remove()     {        it.remove(); }
3089                 public void forEachRemaining(Consumer<? super E> action) {
3090                     it.forEachRemaining(action);
3091                 }
3092             };
3093         }
3094 
3095         public boolean add(E e)          { return c.add(typeCheck(e)); }
3096 
3097         private E[] zeroLengthElementArray; // Lazily initialized
3098 
3099         private E[] zeroLengthElementArray() {
3100             return zeroLengthElementArray != null ? zeroLengthElementArray :
3101                 (zeroLengthElementArray = zeroLengthArray(type));
3102         }
3103 
3104         @SuppressWarnings("unchecked")
3105         Collection<E> checkedCopyOf(Collection<? extends E> coll) {
3106             Object[] a;
3107             try {
3108                 E[] z = zeroLengthElementArray();
3109                 a = coll.toArray(z);
3110                 // Defend against coll violating the toArray contract
3111                 if (a.getClass() != z.getClass())
3112                     a = Arrays.copyOf(a, a.length, z.getClass());


3748             CheckedEntrySet(Set<Map.Entry<K, V>> s, Class<V> valueType) {
3749                 this.s = s;
3750                 this.valueType = valueType;
3751             }
3752 
3753             public int size()        { return s.size(); }
3754             public boolean isEmpty() { return s.isEmpty(); }
3755             public String toString() { return s.toString(); }
3756             public int hashCode()    { return s.hashCode(); }
3757             public void clear()      {        s.clear(); }
3758 
3759             public boolean add(Map.Entry<K, V> e) {
3760                 throw new UnsupportedOperationException();
3761             }
3762             public boolean addAll(Collection<? extends Map.Entry<K, V>> coll) {
3763                 throw new UnsupportedOperationException();
3764             }
3765 
3766             public Iterator<Map.Entry<K,V>> iterator() {
3767                 final Iterator<Map.Entry<K, V>> i = s.iterator();

3768 
3769                 return new Iterator<Map.Entry<K,V>>() {
3770                     public boolean hasNext() { return i.hasNext(); }
3771                     public void remove()     { i.remove(); }
3772 
3773                     public Map.Entry<K,V> next() {
3774                         return checkedEntry(i.next(), valueType);
3775                     }
3776 
3777                     public void forEachRemaining(Consumer<? super Entry<K, V>> action) {
3778                         i.forEachRemaining(
3779                             e -> action.accept(checkedEntry(e, valueType)));
3780                     }
3781                 };
3782             }
3783 
3784             @SuppressWarnings("unchecked")
3785             public Object[] toArray() {
3786                 Object[] source = s.toArray();
3787 
3788                 /*
3789                  * Ensure that we don't get an ArrayStoreException even if
3790                  * s.toArray returns an array of something other than Object
3791                  */
3792                 Object[] dest = (source.getClass() == Object[].class)
3793                     ? source
3794                     : new Object[source.length];
3795 
3796                 for (int i = 0; i < source.length; i++)
3797                     dest[i] = checkedEntry((Map.Entry<K,V>)source[i],
3798                                            valueType);
3799                 return dest;


< prev index next >