Как найти и удалить элемент из Scala ListBuffer? - PullRequest
0 голосов
/ 18 ноября 2018

Следующий код выдает UnsupportedOperationException в Scala 2.12.7 и Java 11.0.1.

listBuffer
.iterator
.dropWhile(_ != u)
.asJava
.remove()

Почему? ListBuffer является изменяемым, и использование Iterator для удаления элементов при обходе должно быть допустимым. ListBuffer содержит Int.

java.lang.UnsupportedOperationException was thrown.
java.lang.UnsupportedOperationException
    at scala.collection.convert.Wrappers$IteratorWrapper.remove(Wrappers.scala:31)
    at scala.collection.convert.Wrappers$IteratorWrapper.remove(Wrappers.scala:26)
    at week4.UndirectedGraph.$anonfun$removeVertex$2(UndirectedGraph.scala:52)
    at scala.runtime.java8.JFunction1$mcVI$sp.apply(JFunction1$mcVI$sp.java:12)
    at scala.collection.immutable.List.foreach(List.scala:388)
    at scala.collection.generic.TraversableForwarder.foreach(TraversableForwarder.scala:34)
    at scala.collection.generic.TraversableForwarder.foreach$(TraversableForwarder.scala:34)
    at scala.collection.mutable.ListBuffer.foreach(ListBuffer.scala:43)
    at week4.UndirectedGraph.$anonfun$removeVertex$1(UndirectedGraph.scala:50)

Изменить: Не является дубликатом этого вопроса, поскольку проблема заключается в том, что он пытается структурно изменить список, возвращаемый Arrays.asList. Мне не нужно указывать очевидное, если бы не люди, которые не знают ответа, но обычно первыми пытаются закрыть вопрос как дубликат.

Ответы [ 2 ]

0 голосов
/ 18 ноября 2018

Вот код источника , выдающий ошибку:

 case class IteratorWrapper[A](underlying: Iterator[A]) extends ju.Iterator[A] with ju.Enumeration[A] {
    def hasNext = underlying.hasNext
    def next() = underlying.next()
    def hasMoreElements = underlying.hasNext
    def nextElement() = underlying.next()
    override def remove() = throw new UnsupportedOperationException
  }

Обратите внимание, что не имеет значения, является ли базовая коллекция изменчивой или нет.

Я думаю, что эта реализация имеет смысл. Итераторы Scala не поддерживают дизайн remove(); их преобразование в Java также должно привести к итераторам, которые ведут себя одинаково.

0 голосов
/ 18 ноября 2018

Не прямой ответ на ваш вопрос, а решение, если вам нужно только удалить элементы, основанные на равенстве объектов, как в примере кода:

Использовать -= метод ListBuffer.Это удаляет все вхождения элемента из ListBuffer, не создавая копию структуры.

  def main(args: Array[String]): Unit = {
    val u = 999
    val listBuffer = new ListBuffer[Int]
    listBuffer ++= Seq(1, 7, 3, 8, 0, 3, 6, 7, 999, 5, 7, 8, 999, 1, 5, 999)
    println(listBuffer)
    listBuffer -= u
    println(listBuffer)
  }

Если вы использовали метод filter, чем вы можете использовать предикат, но копию ListBuffer будет создано:

  def main(args: Array[String]): Unit = {
    val u = 999
    var listBuffer = new ListBuffer[Int]
    listBuffer ++= Seq(1, 7, 3, 8, 0, 3, 6, 7, 999, 5, 7, 8, 999, 1, 5, 999)
    println(listBuffer)
    listBuffer = listBuffer.filter(_ != u)
    println(listBuffer)
  }
...