Java 如何防止迭代器列表的变异?
我希望避免其他人对迭代器Java 如何防止迭代器列表的变异?,java,iterator,immutability,Java,Iterator,Immutability,我希望避免其他人对迭代器测试的输入列表进行变异。我只希望其他人在测试的深层副本上运行 如何在Java中实现这一点 下面是一个例子,显示了突变对测试的影响。这两部分都在对输入进行排序。但是第二部分没有什么需要排序的,因为第一部分的变异将迭代器迭代到最后 您可以在此处联机运行以下示例: 导入java.util.*; 公共类不可变示例{ 公共静态void main(字符串[]args){ System.out.println(“按需排序”); List mutableTests=Arrays.as
测试的输入列表进行变异。我只希望其他人在测试的深层副本上运行
如何在Java中实现这一点
下面是一个例子,显示了突变对测试的影响。这两部分都在对输入进行排序。但是第二部分没有什么需要排序的,因为第一部分的变异将迭代器迭代到最后
您可以在此处联机运行以下示例:
导入java.util.*;
公共类不可变示例{
公共静态void main(字符串[]args){
System.out.println(“按需排序”);
List mutableTests=Arrays.asList(
Arrays.asList(1,2).iterator(),
Arrays.asList(0.iterator(),
Collections.emptyIterator()
);
列表测试=集合。不可修改列表(可变测试);
MergingIterator MergingIterator=新的MergingIterator(测试);
while(mergingIterator.hasNext()){
System.out.println(mergingIterator.next());
}
System.out.println(“一次排序”);
/*取消注释以下内容将看到相同的结果:*/
//tests=Arrays.asList(
//Arrays.asList(1,2).iterator(),
//Arrays.asList(0.iterator(),
//Collections.emptyIterator()
// );
MergeKSortedIterators sol=新的MergeKSortedIterators();
Iterable result=sol.Mergeksortedirators(测试);
for(整数num:result){
系统输出打印项数(num);
}
}
}
类PeekingIterator实现了迭代器,可比较{
迭代器;
整型peek元素;
布尔偷看;
公共窥视迭代器(迭代器迭代器){
this.iterator=迭代器;
}
公共布尔hasNext(){
return haspeek | |迭代器.hasNext();
}
公共整数next(){
int-nextElem=haspeek?peek元素:迭代器.next();
haspeek=false;
返回NEXTLEM;
}
公共整数peek(){
peek元素=haspeek?peek元素:迭代器.next();
haspeek=true;
返回元素;
}
@凌驾
公共整数比较(PeekingIterator){
返回this.peek()-that.peek();
}
}
类MergingIterator实现了迭代器{
队列堆;
公共MergingIterator(列表迭代器){
//minHeap=newpriorityqueue((x,y)->x.peek().compareTo(y.peek());
minHeap=new PriorityQueue();
for(迭代器迭代器:迭代器){
if(iterator.hasNext()){
offer(新的PeekingIterator(迭代器));
}
}
}
公共布尔hasNext(){
return!minHeap.isEmpty();
}
公共整数next(){
PeekingIterator nextite=minHeap.poll();
整数next=nextIter.next();
if(nextIter.hasNext()){
minHeap.offer(nextIter);
}
下一步返回;
}
}
类mergeksortedirators{
公共Iterable mergeksortedirators(列表迭代器列表){
列表结果=新建ArrayList();
if(iteratorList.isEmpty()){
返回结果;
}
PriorityQueue pq=新的PriorityQueue();
for(迭代器迭代器:迭代器列表){
if(iterator.hasNext()){
添加(新的PeekingIterator(迭代器));
}
}
而(!pq.isEmpty()){
PeekingIterator curr=pq.poll();
//添加(curr.peek());
//无法将此项用作hasNext()对“HasPeek”的检查`
result.add(curr.next());
if(curr.hasNext()){
新增产品质量(当前);
}
}
返回结果;
}
}
这个问题似乎是基于一种误解。。。一两个
如何防止迭代器列表的变异
您需要区分列表的易变性和列表中项目的易变性。我想你实际上是在问后者。(因此,清单与问题并不真正相关。我们将看到。)
我希望避免其他人对迭代器测试的输入列表进行变异
同样,您似乎在询问列表,但我认为您实际上是想询问迭代器
我只希望其他人在测试的深层副本上运行
这意味着您希望迭代器是不可变的
问题是:
迭代器是一个固有的有状态/可变对象。实际上,如果不改变迭代器对象,就无法实现next()
迭代器
对象通常不可深度复制。它们通常不支持clone()
或公共构造函数,并且通常不实现Serializable
。(事实上,如果它们是可序列化的,序列化/反序列化的语义就会有问题。)
因此,基本上,你所设想的不可变迭代器列表或(以某种方式)生成迭代器深度副本的列表是不实际的
你评论道:
所以List tests=Collections.unmodifiableList(mutableTests)代码>无法为列表生成不可修改的列表
嗯,是的,它可以。但这并不能解决问题。您需要一个不可修改的迭代器列表,而不是一个不可修改的迭代器列表
可能的解决办法:
您可以从迭代器的基本集合中为每个测试运行重新创建迭代器列表
使用Iterable
而不是Iterator
。您正在使用的集合类型都实现了Iterable,第三个迭代器可以从空列表中创建
List<Iterable<Integer>> tests = Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(0),
Collections.emptyList()
);
// to use them ...
for (Iterable<Integer> iterable : tests) {
Iterator<Integer> iterator = iterable.iterator();
// etc ...
}
List tests=Arrays.asList(
数组。asList(1,2),
数组。asList(0),
List<Iterable<Integer>> tests = Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(0),
Collections.emptyList()
);
// to use them ...
for (Iterable<Integer> iterable : tests) {
Iterator<Integer> iterator = iterable.iterator();
// etc ...
}