src/share/classes/java/util/Spliterators.java

Print this page
rev 7572 : 8017141: java.util/stream Spliterators from sequential sources should not catch OOME
Reviewed-by:
Contributed-by: paul.sandoz@oracle.com


1297              * Split into arrays of arithmetically increasing batch
1298              * sizes.  This will only improve parallel performance if
1299              * per-element Consumer actions are more costly than
1300              * transferring them into an array.  The use of an
1301              * arithmetic progression in split sizes provides overhead
1302              * vs parallelism bounds that do not particularly favor or
1303              * penalize cases of lightweight vs heavyweight element
1304              * operations, across combinations of #elements vs #cores,
1305              * whether or not either are known.  We generate
1306              * O(sqrt(#elements)) splits, allowing O(sqrt(#cores))
1307              * potential speedup.
1308              */
1309             HoldingConsumer<T> holder = new HoldingConsumer<>();
1310             long s = est;
1311             if (s > 1 && tryAdvance(holder)) {
1312                 int n = batch + BATCH_UNIT;
1313                 if (n > s)
1314                     n = (int) s;
1315                 if (n > MAX_BATCH)
1316                     n = MAX_BATCH;
1317                 Object[] a;
1318                 try {
1319                     a = new Object[n];
1320                 } catch (OutOfMemoryError oome) {
1321                     return null;
1322                 }
1323                 int j = 0;
1324                 do { a[j] = holder.value; } while (++j < n && tryAdvance(holder));
1325                 batch = j;
1326                 if (est != Long.MAX_VALUE)
1327                     est -= j;
1328                 return new ArraySpliterator<>(a, 0, j, characteristics());
1329             }
1330             return null;
1331         }
1332 
1333         /**
1334          * {@inheritDoc}
1335          *
1336          * @implSpec
1337          * This implementation returns the estimated size as reported when
1338          * created and, if the estimate size is known, decreases in size when
1339          * split.
1340          */
1341         @Override
1342         public long estimateSize() {


1412             public void accept(int value) {
1413                 this.value = value;
1414             }
1415         }
1416 
1417         /**
1418          * {@inheritDoc}
1419          *
1420          * This implementation permits limited parallelism.
1421          */
1422         @Override
1423         public Spliterator.OfInt trySplit() {
1424             HoldingIntConsumer holder = new HoldingIntConsumer();
1425             long s = est;
1426             if (s > 1 && tryAdvance(holder)) {
1427                 int n = batch + BATCH_UNIT;
1428                 if (n > s)
1429                     n = (int) s;
1430                 if (n > MAX_BATCH)
1431                     n = MAX_BATCH;
1432                 int[] a;
1433                 try {
1434                     a = new int[n];
1435                 } catch (OutOfMemoryError oome) {
1436                     return null;
1437                 }
1438                 int j = 0;
1439                 do { a[j] = holder.value; } while (++j < n && tryAdvance(holder));
1440                 batch = j;
1441                 if (est != Long.MAX_VALUE)
1442                     est -= j;
1443                 return new IntArraySpliterator(a, 0, j, characteristics());
1444             }
1445             return null;
1446         }
1447 
1448         /**
1449          * {@inheritDoc}
1450          *
1451          * @implSpec
1452          * This implementation returns the estimated size as reported when
1453          * created and, if the estimate size is known, decreases in size when
1454          * split.
1455          */
1456         @Override
1457         public long estimateSize() {


1527             public void accept(long value) {
1528                 this.value = value;
1529             }
1530         }
1531 
1532         /**
1533          * {@inheritDoc}
1534          *
1535          * This implementation permits limited parallelism.
1536          */
1537         @Override
1538         public Spliterator.OfLong trySplit() {
1539             HoldingLongConsumer holder = new HoldingLongConsumer();
1540             long s = est;
1541             if (s > 1 && tryAdvance(holder)) {
1542                 int n = batch + BATCH_UNIT;
1543                 if (n > s)
1544                     n = (int) s;
1545                 if (n > MAX_BATCH)
1546                     n = MAX_BATCH;
1547                 long[] a;
1548                 try {
1549                     a = new long[n];
1550                 } catch (OutOfMemoryError oome) {
1551                     return null;
1552                 }
1553                 int j = 0;
1554                 do { a[j] = holder.value; } while (++j < n && tryAdvance(holder));
1555                 batch = j;
1556                 if (est != Long.MAX_VALUE)
1557                     est -= j;
1558                 return new LongArraySpliterator(a, 0, j, characteristics());
1559             }
1560             return null;
1561         }
1562 
1563         /**
1564          * {@inheritDoc}
1565          *
1566          * @implSpec
1567          * This implementation returns the estimated size as reported when
1568          * created and, if the estimate size is known, decreases in size when
1569          * split.
1570          */
1571         @Override
1572         public long estimateSize() {


1642             public void accept(double value) {
1643                 this.value = value;
1644             }
1645         }
1646 
1647         /**
1648          * {@inheritDoc}
1649          *
1650          * This implementation permits limited parallelism.
1651          */
1652         @Override
1653         public Spliterator.OfDouble trySplit() {
1654             HoldingDoubleConsumer holder = new HoldingDoubleConsumer();
1655             long s = est;
1656             if (s > 1 && tryAdvance(holder)) {
1657                 int n = batch + BATCH_UNIT;
1658                 if (n > s)
1659                     n = (int) s;
1660                 if (n > MAX_BATCH)
1661                     n = MAX_BATCH;
1662                 double[] a;
1663                 try {
1664                     a = new double[n];
1665                 } catch (OutOfMemoryError oome) {
1666                     return null;
1667                 }
1668                 int j = 0;
1669                 do { a[j] = holder.value; } while (++j < n && tryAdvance(holder));
1670                 batch = j;
1671                 if (est != Long.MAX_VALUE)
1672                     est -= j;
1673                 return new DoubleArraySpliterator(a, 0, j, characteristics());
1674             }
1675             return null;
1676         }
1677 
1678         /**
1679          * {@inheritDoc}
1680          *
1681          * @implSpec
1682          * This implementation returns the estimated size as reported when
1683          * created and, if the estimate size is known, decreases in size when
1684          * split.
1685          */
1686         @Override
1687         public long estimateSize() {


1778              * penalize cases of lightweight vs heavyweight element
1779              * operations, across combinations of #elements vs #cores,
1780              * whether or not either are known.  We generate
1781              * O(sqrt(#elements)) splits, allowing O(sqrt(#cores))
1782              * potential speedup.
1783              */
1784             Iterator<? extends T> i;
1785             long s;
1786             if ((i = it) == null) {
1787                 i = it = collection.iterator();
1788                 s = est = (long) collection.size();
1789             }
1790             else
1791                 s = est;
1792             if (s > 1 && i.hasNext()) {
1793                 int n = batch + BATCH_UNIT;
1794                 if (n > s)
1795                     n = (int) s;
1796                 if (n > MAX_BATCH)
1797                     n = MAX_BATCH;
1798                 Object[] a;
1799                 try {
1800                     a = new Object[n];
1801                 } catch (OutOfMemoryError oome) {
1802                     return null;
1803                 }
1804                 int j = 0;
1805                 do { a[j] = i.next(); } while (++j < n && i.hasNext());
1806                 batch = j;
1807                 if (est != Long.MAX_VALUE)
1808                     est -= j;
1809                 return new ArraySpliterator<>(a, 0, j, characteristics);
1810             }
1811             return null;
1812         }
1813 
1814         @Override
1815         public void forEachRemaining(Consumer<? super T> action) {
1816             if (action == null) throw new NullPointerException();
1817             Iterator<? extends T> i;
1818             if ((i = it) == null) {
1819                 i = it = collection.iterator();
1820                 est = (long)collection.size();
1821             }
1822             i.forEachRemaining(action);
1823         }


1893          * @param iterator the iterator for the source
1894          * @param characteristics properties of this spliterator's
1895          * source or elements.
1896          */
1897         public IntIteratorSpliterator(PrimitiveIterator.OfInt iterator, int characteristics) {
1898             this.it = iterator;
1899             this.est = Long.MAX_VALUE;
1900             this.characteristics = characteristics & ~(Spliterator.SIZED | Spliterator.SUBSIZED);
1901         }
1902 
1903         @Override
1904         public OfInt trySplit() {
1905             PrimitiveIterator.OfInt i = it;
1906             long s = est;
1907             if (s > 1 && i.hasNext()) {
1908                 int n = batch + BATCH_UNIT;
1909                 if (n > s)
1910                     n = (int) s;
1911                 if (n > MAX_BATCH)
1912                     n = MAX_BATCH;
1913                 int[] a;
1914                 try {
1915                     a = new int[n];
1916                 } catch (OutOfMemoryError oome) {
1917                     return null;
1918                 }
1919                 int j = 0;
1920                 do { a[j] = i.nextInt(); } while (++j < n && i.hasNext());
1921                 batch = j;
1922                 if (est != Long.MAX_VALUE)
1923                     est -= j;
1924                 return new IntArraySpliterator(a, 0, j, characteristics);
1925             }
1926             return null;
1927         }
1928 
1929         @Override
1930         public void forEachRemaining(IntConsumer action) {
1931             if (action == null) throw new NullPointerException();
1932             it.forEachRemaining(action);
1933         }
1934 
1935         @Override
1936         public boolean tryAdvance(IntConsumer action) {
1937             if (action == null) throw new NullPointerException();
1938             if (it.hasNext()) {


1990          * @param iterator the iterator for the source
1991          * @param characteristics properties of this spliterator's
1992          * source or elements.
1993          */
1994         public LongIteratorSpliterator(PrimitiveIterator.OfLong iterator, int characteristics) {
1995             this.it = iterator;
1996             this.est = Long.MAX_VALUE;
1997             this.characteristics = characteristics & ~(Spliterator.SIZED | Spliterator.SUBSIZED);
1998         }
1999 
2000         @Override
2001         public OfLong trySplit() {
2002             PrimitiveIterator.OfLong i = it;
2003             long s = est;
2004             if (s > 1 && i.hasNext()) {
2005                 int n = batch + BATCH_UNIT;
2006                 if (n > s)
2007                     n = (int) s;
2008                 if (n > MAX_BATCH)
2009                     n = MAX_BATCH;
2010                 long[] a;
2011                 try {
2012                     a = new long[n];
2013                 } catch (OutOfMemoryError oome) {
2014                     return null;
2015                 }
2016                 int j = 0;
2017                 do { a[j] = i.nextLong(); } while (++j < n && i.hasNext());
2018                 batch = j;
2019                 if (est != Long.MAX_VALUE)
2020                     est -= j;
2021                 return new LongArraySpliterator(a, 0, j, characteristics);
2022             }
2023             return null;
2024         }
2025 
2026         @Override
2027         public void forEachRemaining(LongConsumer action) {
2028             if (action == null) throw new NullPointerException();
2029             it.forEachRemaining(action);
2030         }
2031 
2032         @Override
2033         public boolean tryAdvance(LongConsumer action) {
2034             if (action == null) throw new NullPointerException();
2035             if (it.hasNext()) {


2087          * @param iterator the iterator for the source
2088          * @param characteristics properties of this spliterator's
2089          * source or elements.
2090          */
2091         public DoubleIteratorSpliterator(PrimitiveIterator.OfDouble iterator, int characteristics) {
2092             this.it = iterator;
2093             this.est = Long.MAX_VALUE;
2094             this.characteristics = characteristics & ~(Spliterator.SIZED | Spliterator.SUBSIZED);
2095         }
2096 
2097         @Override
2098         public OfDouble trySplit() {
2099             PrimitiveIterator.OfDouble i = it;
2100             long s = est;
2101             if (s > 1 && i.hasNext()) {
2102                 int n = batch + BATCH_UNIT;
2103                 if (n > s)
2104                     n = (int) s;
2105                 if (n > MAX_BATCH)
2106                     n = MAX_BATCH;
2107                 double[] a;
2108                 try {
2109                     a = new double[n];
2110                 } catch (OutOfMemoryError oome) {
2111                     return null;
2112                 }
2113                 int j = 0;
2114                 do { a[j] = i.nextDouble(); } while (++j < n && i.hasNext());
2115                 batch = j;
2116                 if (est != Long.MAX_VALUE)
2117                     est -= j;
2118                 return new DoubleArraySpliterator(a, 0, j, characteristics);
2119             }
2120             return null;
2121         }
2122 
2123         @Override
2124         public void forEachRemaining(DoubleConsumer action) {
2125             if (action == null) throw new NullPointerException();
2126             it.forEachRemaining(action);
2127         }
2128 
2129         @Override
2130         public boolean tryAdvance(DoubleConsumer action) {
2131             if (action == null) throw new NullPointerException();
2132             if (it.hasNext()) {




1297              * Split into arrays of arithmetically increasing batch
1298              * sizes.  This will only improve parallel performance if
1299              * per-element Consumer actions are more costly than
1300              * transferring them into an array.  The use of an
1301              * arithmetic progression in split sizes provides overhead
1302              * vs parallelism bounds that do not particularly favor or
1303              * penalize cases of lightweight vs heavyweight element
1304              * operations, across combinations of #elements vs #cores,
1305              * whether or not either are known.  We generate
1306              * O(sqrt(#elements)) splits, allowing O(sqrt(#cores))
1307              * potential speedup.
1308              */
1309             HoldingConsumer<T> holder = new HoldingConsumer<>();
1310             long s = est;
1311             if (s > 1 && tryAdvance(holder)) {
1312                 int n = batch + BATCH_UNIT;
1313                 if (n > s)
1314                     n = (int) s;
1315                 if (n > MAX_BATCH)
1316                     n = MAX_BATCH;
1317                 Object[] a = new Object[n];





1318                 int j = 0;
1319                 do { a[j] = holder.value; } while (++j < n && tryAdvance(holder));
1320                 batch = j;
1321                 if (est != Long.MAX_VALUE)
1322                     est -= j;
1323                 return new ArraySpliterator<>(a, 0, j, characteristics());
1324             }
1325             return null;
1326         }
1327 
1328         /**
1329          * {@inheritDoc}
1330          *
1331          * @implSpec
1332          * This implementation returns the estimated size as reported when
1333          * created and, if the estimate size is known, decreases in size when
1334          * split.
1335          */
1336         @Override
1337         public long estimateSize() {


1407             public void accept(int value) {
1408                 this.value = value;
1409             }
1410         }
1411 
1412         /**
1413          * {@inheritDoc}
1414          *
1415          * This implementation permits limited parallelism.
1416          */
1417         @Override
1418         public Spliterator.OfInt trySplit() {
1419             HoldingIntConsumer holder = new HoldingIntConsumer();
1420             long s = est;
1421             if (s > 1 && tryAdvance(holder)) {
1422                 int n = batch + BATCH_UNIT;
1423                 if (n > s)
1424                     n = (int) s;
1425                 if (n > MAX_BATCH)
1426                     n = MAX_BATCH;
1427                 int[] a = new int[n];





1428                 int j = 0;
1429                 do { a[j] = holder.value; } while (++j < n && tryAdvance(holder));
1430                 batch = j;
1431                 if (est != Long.MAX_VALUE)
1432                     est -= j;
1433                 return new IntArraySpliterator(a, 0, j, characteristics());
1434             }
1435             return null;
1436         }
1437 
1438         /**
1439          * {@inheritDoc}
1440          *
1441          * @implSpec
1442          * This implementation returns the estimated size as reported when
1443          * created and, if the estimate size is known, decreases in size when
1444          * split.
1445          */
1446         @Override
1447         public long estimateSize() {


1517             public void accept(long value) {
1518                 this.value = value;
1519             }
1520         }
1521 
1522         /**
1523          * {@inheritDoc}
1524          *
1525          * This implementation permits limited parallelism.
1526          */
1527         @Override
1528         public Spliterator.OfLong trySplit() {
1529             HoldingLongConsumer holder = new HoldingLongConsumer();
1530             long s = est;
1531             if (s > 1 && tryAdvance(holder)) {
1532                 int n = batch + BATCH_UNIT;
1533                 if (n > s)
1534                     n = (int) s;
1535                 if (n > MAX_BATCH)
1536                     n = MAX_BATCH;
1537                 long[] a = new long[n];





1538                 int j = 0;
1539                 do { a[j] = holder.value; } while (++j < n && tryAdvance(holder));
1540                 batch = j;
1541                 if (est != Long.MAX_VALUE)
1542                     est -= j;
1543                 return new LongArraySpliterator(a, 0, j, characteristics());
1544             }
1545             return null;
1546         }
1547 
1548         /**
1549          * {@inheritDoc}
1550          *
1551          * @implSpec
1552          * This implementation returns the estimated size as reported when
1553          * created and, if the estimate size is known, decreases in size when
1554          * split.
1555          */
1556         @Override
1557         public long estimateSize() {


1627             public void accept(double value) {
1628                 this.value = value;
1629             }
1630         }
1631 
1632         /**
1633          * {@inheritDoc}
1634          *
1635          * This implementation permits limited parallelism.
1636          */
1637         @Override
1638         public Spliterator.OfDouble trySplit() {
1639             HoldingDoubleConsumer holder = new HoldingDoubleConsumer();
1640             long s = est;
1641             if (s > 1 && tryAdvance(holder)) {
1642                 int n = batch + BATCH_UNIT;
1643                 if (n > s)
1644                     n = (int) s;
1645                 if (n > MAX_BATCH)
1646                     n = MAX_BATCH;
1647                 double[] a = new double[n];





1648                 int j = 0;
1649                 do { a[j] = holder.value; } while (++j < n && tryAdvance(holder));
1650                 batch = j;
1651                 if (est != Long.MAX_VALUE)
1652                     est -= j;
1653                 return new DoubleArraySpliterator(a, 0, j, characteristics());
1654             }
1655             return null;
1656         }
1657 
1658         /**
1659          * {@inheritDoc}
1660          *
1661          * @implSpec
1662          * This implementation returns the estimated size as reported when
1663          * created and, if the estimate size is known, decreases in size when
1664          * split.
1665          */
1666         @Override
1667         public long estimateSize() {


1758              * penalize cases of lightweight vs heavyweight element
1759              * operations, across combinations of #elements vs #cores,
1760              * whether or not either are known.  We generate
1761              * O(sqrt(#elements)) splits, allowing O(sqrt(#cores))
1762              * potential speedup.
1763              */
1764             Iterator<? extends T> i;
1765             long s;
1766             if ((i = it) == null) {
1767                 i = it = collection.iterator();
1768                 s = est = (long) collection.size();
1769             }
1770             else
1771                 s = est;
1772             if (s > 1 && i.hasNext()) {
1773                 int n = batch + BATCH_UNIT;
1774                 if (n > s)
1775                     n = (int) s;
1776                 if (n > MAX_BATCH)
1777                     n = MAX_BATCH;
1778                 Object[] a = new Object[n];





1779                 int j = 0;
1780                 do { a[j] = i.next(); } while (++j < n && i.hasNext());
1781                 batch = j;
1782                 if (est != Long.MAX_VALUE)
1783                     est -= j;
1784                 return new ArraySpliterator<>(a, 0, j, characteristics);
1785             }
1786             return null;
1787         }
1788 
1789         @Override
1790         public void forEachRemaining(Consumer<? super T> action) {
1791             if (action == null) throw new NullPointerException();
1792             Iterator<? extends T> i;
1793             if ((i = it) == null) {
1794                 i = it = collection.iterator();
1795                 est = (long)collection.size();
1796             }
1797             i.forEachRemaining(action);
1798         }


1868          * @param iterator the iterator for the source
1869          * @param characteristics properties of this spliterator's
1870          * source or elements.
1871          */
1872         public IntIteratorSpliterator(PrimitiveIterator.OfInt iterator, int characteristics) {
1873             this.it = iterator;
1874             this.est = Long.MAX_VALUE;
1875             this.characteristics = characteristics & ~(Spliterator.SIZED | Spliterator.SUBSIZED);
1876         }
1877 
1878         @Override
1879         public OfInt trySplit() {
1880             PrimitiveIterator.OfInt i = it;
1881             long s = est;
1882             if (s > 1 && i.hasNext()) {
1883                 int n = batch + BATCH_UNIT;
1884                 if (n > s)
1885                     n = (int) s;
1886                 if (n > MAX_BATCH)
1887                     n = MAX_BATCH;
1888                 int[] a = new int[n];





1889                 int j = 0;
1890                 do { a[j] = i.nextInt(); } while (++j < n && i.hasNext());
1891                 batch = j;
1892                 if (est != Long.MAX_VALUE)
1893                     est -= j;
1894                 return new IntArraySpliterator(a, 0, j, characteristics);
1895             }
1896             return null;
1897         }
1898 
1899         @Override
1900         public void forEachRemaining(IntConsumer action) {
1901             if (action == null) throw new NullPointerException();
1902             it.forEachRemaining(action);
1903         }
1904 
1905         @Override
1906         public boolean tryAdvance(IntConsumer action) {
1907             if (action == null) throw new NullPointerException();
1908             if (it.hasNext()) {


1960          * @param iterator the iterator for the source
1961          * @param characteristics properties of this spliterator's
1962          * source or elements.
1963          */
1964         public LongIteratorSpliterator(PrimitiveIterator.OfLong iterator, int characteristics) {
1965             this.it = iterator;
1966             this.est = Long.MAX_VALUE;
1967             this.characteristics = characteristics & ~(Spliterator.SIZED | Spliterator.SUBSIZED);
1968         }
1969 
1970         @Override
1971         public OfLong trySplit() {
1972             PrimitiveIterator.OfLong i = it;
1973             long s = est;
1974             if (s > 1 && i.hasNext()) {
1975                 int n = batch + BATCH_UNIT;
1976                 if (n > s)
1977                     n = (int) s;
1978                 if (n > MAX_BATCH)
1979                     n = MAX_BATCH;
1980                 long[] a = new long[n];





1981                 int j = 0;
1982                 do { a[j] = i.nextLong(); } while (++j < n && i.hasNext());
1983                 batch = j;
1984                 if (est != Long.MAX_VALUE)
1985                     est -= j;
1986                 return new LongArraySpliterator(a, 0, j, characteristics);
1987             }
1988             return null;
1989         }
1990 
1991         @Override
1992         public void forEachRemaining(LongConsumer action) {
1993             if (action == null) throw new NullPointerException();
1994             it.forEachRemaining(action);
1995         }
1996 
1997         @Override
1998         public boolean tryAdvance(LongConsumer action) {
1999             if (action == null) throw new NullPointerException();
2000             if (it.hasNext()) {


2052          * @param iterator the iterator for the source
2053          * @param characteristics properties of this spliterator's
2054          * source or elements.
2055          */
2056         public DoubleIteratorSpliterator(PrimitiveIterator.OfDouble iterator, int characteristics) {
2057             this.it = iterator;
2058             this.est = Long.MAX_VALUE;
2059             this.characteristics = characteristics & ~(Spliterator.SIZED | Spliterator.SUBSIZED);
2060         }
2061 
2062         @Override
2063         public OfDouble trySplit() {
2064             PrimitiveIterator.OfDouble i = it;
2065             long s = est;
2066             if (s > 1 && i.hasNext()) {
2067                 int n = batch + BATCH_UNIT;
2068                 if (n > s)
2069                     n = (int) s;
2070                 if (n > MAX_BATCH)
2071                     n = MAX_BATCH;
2072                 double[] a = new double[n];





2073                 int j = 0;
2074                 do { a[j] = i.nextDouble(); } while (++j < n && i.hasNext());
2075                 batch = j;
2076                 if (est != Long.MAX_VALUE)
2077                     est -= j;
2078                 return new DoubleArraySpliterator(a, 0, j, characteristics);
2079             }
2080             return null;
2081         }
2082 
2083         @Override
2084         public void forEachRemaining(DoubleConsumer action) {
2085             if (action == null) throw new NullPointerException();
2086             it.forEachRemaining(action);
2087         }
2088 
2089         @Override
2090         public boolean tryAdvance(DoubleConsumer action) {
2091             if (action == null) throw new NullPointerException();
2092             if (it.hasNext()) {