java中无限大_Java 9中的无限集
java中無(wú)限大
一套
甲Set是元素的集合,從而在任何給定的元件Set只出現(xiàn)一次。
更正式地說(shuō),集合不包含元素e1和e2對(duì),因此e1.equals(e2) 。
我們可以像這樣在Java 9中輕松創(chuàng)建Set :
final Set<Integer> s = Set.of(1, 2, 3); System.out.println(s);這可能會(huì)產(chǎn)生以下輸出:
[2, 3, 1]上面產(chǎn)生的Set是不可變的,即它不能更改,并且也是有限的,因?yàn)镾et有不同數(shù)量的元素,即三個(gè)。 未指定通過(guò)其讀取方法(例如stream() , iterator()和forEach() )返回元素的順序。
無(wú)限集
無(wú)限集包含無(wú)限數(shù)量的元素。 無(wú)限集的一個(gè)示例是所有整數(shù)的集合[…,-1,0,1,2,…],其中整數(shù)不是Java Integer類,而是根據(jù)整數(shù)的數(shù)學(xué)定義得出的整數(shù),其中存在對(duì)于任何給定的整數(shù)n,始終為更大的整數(shù)n + 1。
有許多無(wú)限集,例如所有質(zhì)數(shù)的集合,偶數(shù)整數(shù)的集合,斐波那契數(shù)的集合等。
由于明顯的原因,我們無(wú)法預(yù)先計(jì)算和存儲(chǔ)無(wú)限Java Set所有元素。 如果嘗試,最終將耗盡內(nèi)存。
我們必須問(wèn)自己的一個(gè)基本問(wèn)題是:對(duì)于我們擁有的Java類型,實(shí)際上是否存在無(wú)限集? 如果我們有一個(gè)Set<Byte>中有最多256個(gè)元素的Set ,這是遠(yuǎn)離無(wú)限的,同樣的道理也適用于Short ,甚至Integer 。 畢竟,只有大約40億個(gè)不同的Integer對(duì)象,如果使用位圖表示成員身份,則可以在0.5 GB的空間中容納Set<Integer> 。 盡管很大,但不是無(wú)限的。
但是,如果我們談?wù)摰氖荓ong或String元素,那么至少實(shí)際上是在接近無(wú)限集。 要存儲(chǔ)所有Long的位圖,將需要許多PB內(nèi)部存儲(chǔ)空間。 真正的無(wú)限Set將是具有任意長(zhǎng)度的字符[az]的所有可能組合的String Set 。
在繼續(xù)之前,我想提一下,這篇文章中的代碼也可以在GitHub上找到,如文章結(jié)尾處所述。
ImmutableStreamSet
為了擺脫存儲(chǔ)Set元素的范式,我們可以創(chuàng)建一個(gè)ImmutableStreamSet ,僅通過(guò)其stream()方法定義Set的元素。 可以將ImmutableStreamSet定義為如下所示的FunctionalInterface :
@FunctionalInterface public interface ImmutableStreamSet<E> extends Set<E> {// This is the only method we need to implements@Overridepublic Stream<E> stream(); @Overridedefault int size() {return (int) stream().limit(Integer.MAX_VALUE).count();}@Overridedefault boolean contains(Object o) {return stream().anyMatch(e -> Objects.equals(e, o));}@Overridedefault boolean containsAll(Collection<?> c) {return (this == c) ? true : c.stream().allMatch(this::contains);}@Overridedefault boolean isEmpty() {return !stream().findAny().isPresent();}@Overridedefault <T> T[] toArray(T[] a) {return stream().collect(toList()).toArray(a);}@Overridedefault Object[] toArray() {return stream().toArray();}@Overridedefault Spliterator<E> spliterator() {return stream().spliterator();}@Overridedefault Iterator<E> iterator() {return stream().iterator();}@Overridedefault Stream<E> parallelStream() {return stream().parallel();}@Overridedefault void forEach(Consumer<? super E> action) {stream().forEach(action);}// We are immutable@Overridedefault boolean removeIf(Predicate<? super E> filter) {throw new UnsupportedOperationException();}@Overridedefault void clear() {throw new UnsupportedOperationException();}@Overridedefault boolean removeAll(Collection<?> c) {throw new UnsupportedOperationException();}@Overridedefault boolean retainAll(Collection<?> c) {throw new UnsupportedOperationException();}@Overridedefault boolean addAll(Collection<? extends E> c) {throw new UnsupportedOperationException();}@Overridedefault boolean remove(Object o) {throw new UnsupportedOperationException();}@Overridedefault boolean add(E e) {throw new UnsupportedOperationException();}static <E> ImmutableStreamSet<E> of(Supplier<Stream<E>> supplier) {// Check out GitHub to see how this Impl class is implementedreturn new ImmutableStreamSetImpl<>(supplier);}}太棒了,現(xiàn)在我們只需提供像這樣的流提供者就可以創(chuàng)建無(wú)限集:
ImmutableStreamSet<Long> setOfAllLong= LongStream.rangeClosed(Long.MIN_VALUE, Long.MAX_VALUE)::boxed;這將創(chuàng)建一Set所有Long值(例如,具有2 ^ 64個(gè)元素)。 提供流提供程序時(shí),必須確保遵守元素唯一性的Set屬性。 考慮以下非法集:
final ImmutableStreamSet<Long> illegalSet = () -> Stream.of(1l, 2l, 1l);顯然,集合中發(fā)生11次兩次,這使該對(duì)象違反了集合要求。
正如我們將看到的,最好創(chuàng)建我們正在考慮的無(wú)限集的具體類。 上面的默認(rèn)實(shí)現(xiàn)的一個(gè)特殊問(wèn)題是contains()方法可能非常慢。 閱讀下一章,找出原因以及如何解決。
正長(zhǎng)集
讓我們假設(shè)我們要?jiǎng)?chuàng)建一個(gè)包含所有正長(zhǎng)值的Set ,并且希望能夠與其他Set和Object有效地使用Set 。 我們可以這樣去做:
public final class PositiveLongSet implements ImmutableStreamSet<Long> {public static final PositiveLongSet INSTANCE = new PositiveLongSet();private PositiveLongSet() {}@Overridepublic Stream<Long> stream() {return LongStream.rangeClosed(1, Long.MAX_VALUE).boxed();}@Overridepublic int size() {return Integer.MAX_VALUE;}@Overridepublic boolean contains(Object o) {return SetUtil.contains(this, Long.class, other -> other > 0, o);}@Overridepublic boolean isEmpty() {return false;}@Overridepublic String toString() {return SetUtil.toString(this);}}請(qǐng)注意,即使Set很大,我們?nèi)绾巫袷胤椒╯ize()的形式要求,在該方法中我們返回Integer.MAX_VALUE 。 如果Set已在今天定義,則size()可能會(huì)返回long而不是int 。 但是在90年代初,內(nèi)部RAM通常小于1 GB。 我們?cè)陬愔惺褂昧藘煞N實(shí)用程序方法:
SetUtil.toString()采用Set ,對(duì)前八個(gè)元素進(jìn)行迭代,并返回這些元素的String表示形式。
SetUtil.contains()方法采用Set ,Element類型類(此處為L(zhǎng)ong.class )和Predicate ,如果我們Long.class比較的對(duì)象屬于給定Element類型類(如果我們要比較的對(duì)象是null或其他類型,則該Set不包含該對(duì)象)。
這是SetUtil樣子:
final class SetUtil {private static final int TO_STRING_MAX_ELEMENTS = 8;static <E> String toString(Set<E> set) {final List<String> first = set.stream().limit(TO_STRING_MAX_ELEMENTS + 1).map(Object::toString).collect(toList());final String endMarker = first.size() > TO_STRING_MAX_ELEMENTS ? ", ...]" : "]";return first.stream().limit(TO_STRING_MAX_ELEMENTS).collect(joining(", ", "[", endMarker));}static <E> boolean contains(final Set<E> set,final Class<E> clazz,final Predicate<E> predicate,final Object o) {if (o == null) {return false;}if (!(clazz.isAssignableFrom(o.getClass()))) {return false;}final E other = clazz.cast(o);return predicate.test(other);}}有了類ImmutableStreamSet和SetUtil我們現(xiàn)在可以輕松地創(chuàng)建其他無(wú)限集,例如PostitiveEvenLongSet (以下未顯示,請(qǐng)PrimeLongSet編寫(xiě)), PrimeLongSet (包含可以用Long表示的所有素?cái)?shù))甚至FibonacciLongSet (包含所有fibonacci數(shù)字)可以用Long表示)。 這些類如下所示:
PrimeLongSet
public final class PrimeLongSet implements ImmutableStreamSet<Long> {public static final PrimeLongSet INSTANCE = new PrimeLongSet();private PrimeLongSet() {}private static final LongPredicate IS_PRIME =x -> LongStream.rangeClosed(2, (long) Math.sqrt(x)).allMatch(n -> x % n != 0);@Overridepublic Stream<Long> stream() {return LongStream.rangeClosed(2, Long.MAX_VALUE).filter(IS_PRIME).boxed();}@Overridepublic int size() {return Integer.MAX_VALUE; }@Overridepublic boolean contains(Object o) {return SetUtil.contains(this, Long.class, IS_PRIME::test, o);}@Overridepublic boolean isEmpty() {return false;}@Overridepublic String toString() {return SetUtil.toString(this);}}斐波那契長(zhǎng)集
public final class FibonacciLongSet implements ImmutableStreamSet<Long> {public static final FibonacciLongSet INSTANCE = new FibonacciLongSet();private FibonacciLongSet() {}@Overridepublic Stream<Long> stream() {return Stream.concat(Stream.of(0l),Stream.iterate(new Fibonacci(0, 1), Fibonacci::next).mapToLong(Fibonacci::getAsLong).takeWhile(fib -> fib > 0).boxed());}@Overridepublic int size() {return 92;}@Overridepublic boolean contains(Object o) {return SetUtil.contains(this,Long.class,other -> stream().anyMatch(fib -> Objects.equals(fib, other)),o);}@Overridepublic boolean isEmpty() {return false;}@Overridepublic String toString() {return SetUtil.toString(this);}private static class Fibonacci {final long beforeLast;final long last;public Fibonacci(long beforeLast, long last) {this.beforeLast = beforeLast;this.last = last;}public Fibonacci next() {return new Fibonacci(last, last + beforeLast);}public long getAsLong() {return beforeLast + last;}}}注意當(dāng)長(zhǎng)回繞為負(fù)值時(shí),我們?nèi)绾问褂肧tream::takeWhile中斷流。 可以說(shuō),當(dāng)我們進(jìn)行預(yù)計(jì)算并提供92的大小時(shí),我們正在“作弊”,但否則size()會(huì)慢一些。
縫合全部
通過(guò)為這些類的實(shí)例提供帶有靜態(tài)提供程序的接口,我們可以封裝我們的預(yù)定義集,并確保在JVM中只有這樣的一個(gè)實(shí)例,如下所示:
public interface Sets {static Set<Long> positiveLongSet() {return PositiveLongSet.INSTANCE;}static Set<Long> positiveEvenLongSet() {return PositiveEvenLongSet.INSTANCE;}static Set<Long> primeLongSet() {return PrimeLongSet.INSTANCE;}static Set<Long> fibonacciLongSet() {return FibonacciLongSet.INSTANCE;}}我們還可以將代碼封裝在Java 9模塊中,通過(guò)將Sets和ImmutableStreamSet類暴露在項(xiàng)目的最頂層包中,并將所有其他類放在名為“ internal”的包中(不公開(kāi)),以確保僅可見(jiàn)Sets和ImmutableStreamSet類。 )。
這是我們?nèi)绾蝝odule-info.java可能看起來(lái)像規(guī)定,兩個(gè)外露類在com.speedment.infinite_sets在包等,并且實(shí)現(xiàn)類com.speedment.infinite_sets.internal :
module-info.java
module com.speedment.infinite_sets {exports com.speedment.infinite_sets; }嘗試一下
現(xiàn)在,我們可以通過(guò)首先聲明現(xiàn)有模塊的用法來(lái)創(chuàng)建另一個(gè)使用無(wú)限集的模塊,如下所示:
module-info.java
module Infinite_sets_app {requires com.speedment.infinite_sets; }然后,我們可以訪問(wèn)模塊的裸露部分。 這是嘗試無(wú)限集的一種方法:
import static com.speedment.infinite_sets.Sets.*; public class Main {public static void main(String[] args) {Stream.of(Set.of(1, 2, 3),positiveLongSet(),positiveEvenLongSet(),primeLongSet(),fibonacciLongSet()).forEachOrdered(System.out::println);// This actually completes fast due to identity equalitypositiveLongSet().containsAll(positiveLongSet());}}這可能會(huì)產(chǎn)生以下輸出:
[3, 2, 1] [1, 2, 3, 4, 5, 6, 7, 8, ...] [2, 4, 6, 8, 10, 12, 14, 16, ...] [2, 3, 5, 7, 11, 13, 17, 19, ...] [0, 1, 2, 3, 5, 8, 13, 21, ...]參與GitHub
這篇文章中的源代碼可以在GitHub上找到 。
游戲,設(shè)定和比賽…
翻譯自: https://www.javacodegeeks.com/2018/06/infinite-sets-java.html
java中無(wú)限大
總結(jié)
以上是生活随笔為你收集整理的java中无限大_Java 9中的无限集的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 舟加可念什么 舟加可念啥
- 下一篇: 小米手机的设置技巧有什么