我直接使用流分裂器进行库I文档中的低级操作。最近,当我使用流分裂器和交错tryAdvance/trySplit
调用时,我发现了非常奇怪的行为。这是一个简单的代码,用于演示此问题:
import java.util.Arrays;
import java.util.Spliterator;
public class SpliteratorBug {
public static void main(String[] args) {
Integer[][] input = { { 1 }, { 2, 3 }, { 4, 5, 6 }, { 7, 8 }, { 9 } };
Spliterator<Integer> spliterator = Arrays.stream(input).parallel()
.flatMap(Arrays::stream).spliterator();
spliterator.trySplit();
spliterator.tryAdvance(s -> {});
spliterator.trySplit();
spliterator.forEachRemaining(System.out::println);
}
}
输出
5
6
9
正如您所看到的,在平面映射后,我应该得到从1
到9
的连续数字的有序流。我将分裂器分开一次,所以它应该跳到一些中间位置。接下来我从中消耗一个元素并将其拆分一次。之后我打印所有剩余的元素。我希望我将从流尾部有几个连续的元素(可能是零元素,它也会很好)。然而,我得到的是5
和6
,然后突然跳转到9
。
我知道目前在JDK分裂器中并没有这样使用:它们总是在遍历之前分裂。但是,官方documentation并未明确禁止在trySplit
之后致电tryAdvance
。
当我使用直接从集合,数组,生成的源等创建的spliterator时,从未观察到这个问题。只有当spliterator是从具有中间flatMap
的并行流创建的时候才会观察到它。
所以问题是:我是否遇到了这个错误,或者明确禁止某个地方以这种方式使用分裂器?
答案 0 :(得分:5)
来自Spliterator.trySplit()
的文档:
此方法可能因任何原因返回
null
,包括空洞,在遍历开始后无法拆分,数据结构限制和效率考虑。
(强调我的)
因此,文档明确提到在开始遍历后尝试拆分的可能性,并建议无法处理此问题的分裂器可能会返回null
。
因此,对于有序的分裂器,观察到的行为应该被视为错误as described by Misha。一般来说,trySplit()
必须返回前缀分裂器的事实,换句话说,必须将关于下一个项目的所有中间状态移交给新的分裂器,这是Spliterator
的一个特点。 {1}}可能导致错误的API。我把这个问题作为检查我自己的spliterator实现的动机,发现了一个类似的bug ......
答案 1 :(得分:4)
从AbstractWrappingSpliterator
和公司的来源我可以看到,当tryAdvance
时,flatMap
(4,5,6)的输出被缓冲,然后消耗4将(5,6)留在缓冲液中。然后trySplit
正确地将(7,8)拆分为新的Spliterator
,在旧的Spliterator
中留下9,但缓冲的(5,6)留在旧的Spliterator
。
所以这看起来像是一个错误。它应该将缓冲区关闭到新的null
或返回enter code here
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.costum.android.widget.LoadMoreListView
android:id="@+id/loadmorelistview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</RelativeLayout>
secondpagead.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<com.nirhart.parallaxscroll.views.ParallaxScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:parallax_factor="1.9"
tools:context=".MainActivity" >
<LinearLayout
android:id="@+id/story_page_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/cover_image_wrapper"
android:layout_width="fill_parent"
android:layout_height="200dip"
android:orientation="vertical" >
<ImageView
android:id="@+id/cover_image"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/cover_img" />
</LinearLayout>
<LinearLayout
android:id="@+id/story_desc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#ffffff"
>
<LinearLayout
android:id="@+id/story_page_title_wrapper"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="#cccccc"
android:orientation="vertical"
android:padding="10dip" >
<TextView
android:id="@+id/story_page_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="SourceSansPro-Bold"
android:gravity="center"
android:lineSpacingMultiplier="1.1"
android:text="@string/stry_title"
android:textColor="#333"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:id="@+id/story_details"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dip" >
<LinearLayout
android:id="@+id/teller_detailWrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="3" >
<ImageView
android:id="@+id/teller_Img"
android:layout_width="40dp"
android:layout_height="50dp"
android:layout_weight="1"
/>
<LinearLayout
android:id="@+id/tellername_desig"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_weight="1.8"
android:orientation="vertical" >
<TextView
android:id="@+id/story_writer_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/writer_name"
android:textAllCaps="true"
android:textColor="#34495e"
android:textSize="12sp" />
<LinearLayout
android:id="@+id/story_Date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dip"
android:orientation="horizontal" >
<ImageView
android:id="@+id/clockImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:src="@drawable/clock_icon" />
<TextView
android:id="@+id/story_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dip"
android:text="@string/story_create_date"
android:textAllCaps="true"
android:textColor="#868686"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/story_category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_weight="0.2"
android:background="#e74c3c"
android:paddingBottom="5dip"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:paddingTop="5dip"
android:text="@string/new_story_category"
android:textColor="#fff"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/story_meta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dip"
android:orientation="horizontal" >
<LinearLayout
android:id="@+id/storyviews"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="6" >
<ImageView
android:id="@+id/viewimg_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dip"
android:layout_weight="1"
android:src="@drawable/eye_icon" />
<TextView
android:id="@+id/stryview_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_weight="1"
android:text="542.5k"
android:textColor="#868686"
android:textSize="12sp" />
<ImageView
android:id="@+id/imageimg_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginTop="2dip"
android:layout_weight="1"
android:src="@drawable/image_icon" />
<TextView
android:id="@+id/stryimage_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_weight="1"
android:text="25"
android:textColor="#868686"
android:textSize="12sp" />
<ImageView
android:id="@+id/shareimg_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginTop="2dip"
android:layout_weight="1"
android:src="@drawable/share_icon" />
<TextView
android:id="@+id/stryshare_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_weight="1"
android:text="542.5k"
android:textColor="#868686"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/stry_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:fontFamily="Georgia.ttf"
android:lineSpacingExtra="3dp"
android:text="@string/stry_description_text"
android:textColor="#333"
android:textSize="16sp" />
</LinearLayout></LinearLayout></RelativeLayout>
,如果缓冲区不为空,则拒绝拆分。
答案 2 :(得分:2)
此行为被正式认定为一个错误(请参阅JDK-8148838),由我修复并推入JDK-9主干(请参阅changeset)。令人遗憾的是,我的初始修补程序实际上修复了flatMap
后的拆分(请参阅webrev),但此修补程序因此情况被拒绝(在trySplit()
之后使用tryAdvance()
)被认为是不常见和气馁。当前接受的解决方案是在完成预设之后禁用WrappingSpliterator
拆分,这足以解决问题。