Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在没有外部库的情况下就地筛选Java列表_Java_List_Collections_Java 7 - Fatal编程技术网

在没有外部库的情况下就地筛选Java列表

在没有外部库的情况下就地筛选Java列表,java,list,collections,java-7,Java,List,Collections,Java 7,这个问题类似于“基于谓词过滤ajava.util.Collection” 由于列表较大,因此无法在适当的位置完成筛选(O(1)memory,不包括输入) 不得使用外部库(即Guava、Apache commons等) Java 7兼容(无Java 8流) 我们可以假设java.util.Collection类型是实现.remove(int)的java.util.List 可能的解决办法: 在列表的迭代器上使用.remove()方法。这可能引发不支持操作异常,因为迭代器上可选地支持.remo

这个问题类似于“基于谓词过滤a
java.util.Collection

  • 由于列表较大,因此无法在适当的位置完成筛选(
    O(1)
    memory,不包括输入)
  • 不得使用外部库(即Guava、Apache commons等)
  • Java 7兼容(无Java 8流)
我们可以假设
java.util.Collection
类型是实现
.remove(int)
java.util.List

可能的解决办法:

  • 列表的
    迭代器上使用
    .remove()
    方法。这可能引发
    不支持操作异常
    ,因为
    迭代器上可选地支持
    .remove()
    方法
  • 编写我们自己的迭代器,使用索引
    .size()
    .remove(int)
    遍历列表
有没有更简单的解决方案


Iterator.remove()

您可以使用包装的
迭代器来伪造过滤器,并使其与对象一起工作(类似于Prediates的实现方式);然而,还有一些次要问题:

您声明列表非常大,解决方案的内存影响应该是
O(1)
,但是如果不知道正在操作的列表,就无法保证这一点。
remove(int)
操作符可以在实现中分配一个新的列表索引并复制到其中

假设列表不做这样的事情,最好实现自己的迭代器,它接受类似谓词的测试,或者编写一个特定的循环来处理列表

无论如何,这听起来像是一个面试问题。这里有一个例子

public interface MyPredicate<T> {
   public boolean isTrue(T value);
}

public void removeOnTrue(List<T> list, MyPredicate<T> predicate) {
   Iterator<T> iterator = list.iterator();
   while (iterator.hasNext()) {
      T next = iterator.next();
      if (predicate.isTrue(next)) {
         iterator.remove();
      }
   }
}
公共接口MyPredicate{
公共布尔值(T值);
}
public void removeOnTrue(列表,MyPredicate谓词){
迭代器迭代器=list.Iterator();
while(iterator.hasNext()){
T next=iterator.next();
if(谓词isTrue(下一个)){
iterator.remove();
}
}
}
在索引之间使用for循环也是一样的,只是随后必须跟踪索引(并使用索引删除)

要使用上述示例,请执行以下操作:

...
List<String> names = ...;
removeOnTrue(names, new MyPredicate<String>() {
  public boolean isTrue(String value) {
    return value.startsWith("A");
  }
});
...
。。。
名单名称=。。。;
RemoveOnTue(名称,新的MyPredicate(){
公共布尔值isTrue(字符串值){
返回值。以“A”开头;
}
});
...

将产生一个
名称
,其中所有以“a”开头的字符串都被删除。

过滤器
谓词
都是Java8类型,因此如果您不想使用Java8,您需要类似的东西

您可以使用包装的
迭代器来伪造过滤器,并使其与对象一起工作(类似于Prediates的实现方式);然而,还有一些次要问题:

您声明列表非常大,解决方案的内存影响应该是
O(1)
,但是如果不知道正在操作的列表,就无法保证这一点。
remove(int)
操作符可以在实现中分配一个新的列表索引并复制到其中

假设列表不做这样的事情,最好实现自己的迭代器,它接受类似谓词的测试,或者编写一个特定的循环来处理列表

无论如何,这听起来像是一个面试问题。这里有一个例子

public interface MyPredicate<T> {
   public boolean isTrue(T value);
}

public void removeOnTrue(List<T> list, MyPredicate<T> predicate) {
   Iterator<T> iterator = list.iterator();
   while (iterator.hasNext()) {
      T next = iterator.next();
      if (predicate.isTrue(next)) {
         iterator.remove();
      }
   }
}
公共接口MyPredicate{
公共布尔值(T值);
}
public void removeOnTrue(列表,MyPredicate谓词){
迭代器迭代器=list.Iterator();
while(iterator.hasNext()){
T next=iterator.next();
if(谓词isTrue(下一个)){
iterator.remove();
}
}
}
在索引之间使用for循环也是一样的,只是随后必须跟踪索引(并使用索引删除)

要使用上述示例,请执行以下操作:

...
List<String> names = ...;
removeOnTrue(names, new MyPredicate<String>() {
  public boolean isTrue(String value) {
    return value.startsWith("A");
  }
});
...
。。。
名单名称=。。。;
RemoveOnTue(名称,新的MyPredicate(){
公共布尔值isTrue(字符串值){
返回值。以“A”开头;
}
});
...

将生成一个
名称
,删除所有以“a”开头的字符串。

没有适合所有
列表
s的最佳解决方案,这是您永远无法达到Java 8效率的地方,因为作为
接口
方法,Java8的
default
方法可以被任何
List
实现覆盖,该实现为特定类定制了一个实现

当您想要在Java8之前的版本中合理地实现类似的功能时,您必须关注常见的情况。JRE提供的列表中几乎没有
remove(int)
有效的列表,但是
Iterator.remove
无效。但是,考虑<<代码> ARAYLIST/<代码>是最常用的可变<代码>列表< /C>实现,对于该实现,基于迭代器的解决方案对于大列表和大量删除的项目表现不佳。这是因为无论您使用的是
remove(int)
还是
Iterator.remove
,每次删除操作都会将所有后续项移动一个位置,然后才能继续,并且可能会再次删除项。在最坏的情况下,如果谓词匹配所有项,则会产生二次复杂性。因此,为这种情况提供更复杂的解决方案非常重要:

interface Predicate<T> {
    boolean test(T object);
}
public static <T> boolean removeIf(List<T> list, Predicate<? super T> p) {
    if(list instanceof RandomAccess) {
        int num=list.size();
        BitSet bs=new BitSet(num);
        for(int index=0; index<num; index++) {
            if(p.test(list.get(index))) bs.set(index);
        }
        if(bs.isEmpty()) {
            return false;
        }
        for(int dst=bs.nextSetBit(0), src=dst;; dst++, src++) {
            src=bs.nextClearBit(src);
            if(src==num) {
              list.subList(dst, src).clear();
              break;
            }
            list.set(dst, list.get(src));
        }
        return true;
    }
    else {
        boolean changed=false;
        for(Iterator<T> it=list.iterator(); it.hasNext(); ) {
            if(p.test(it.next())) {
                it.remove();
                changed=true;
            }
        }
        return changed;
    }
}
接口谓词{
布尔检验(T对象);
}

public static boolean removeIf(List,Predicate没有适合所有
List
s的最佳解决方案,这是您永远无法达到效率的地方