Scala List.diff .intersect и .union не работают должным образом - PullRequest
0 голосов
/ 16 ноября 2011

Использование приведенного ниже кода приводит к следующему:

List(a, b)
List()
List(a, b, b, c)

То, что я хочу, - это, конечно, результат, подобный следующему:

List(a)
List(b)
List(a, b, b, c)

Я думаю, это потому, что diff union и intersect workотносительно "==".Проблема заключается в том, что оператор "==" - последний и не может быть переопределен в классе "Test".

Как я могу достичь ожидаемого результата?

Здесь используется используемый код:

package scalatest;

public class JStringHolder {
String s = null;

public JStringHolder(String newString){
    s = newString;
}

@Override
public String toString() {
    return s;
}

@Override
public boolean equals(Object obj) {
    System.out.println("SHEQ " + this.s + " AND " + ((JStringHolder)obj).s + " " + this.s.equals(((JStringHolder)obj).s));
    return this.s.equals(((JStringHolder)obj).s);
}
}

И код скалы, который будет выполнен:

package scalatest

object ListTest {

  trait AbstractTest 
  case class Test(stringHolder: scalatest.JStringHolder) extends AbstractTest {
    override def toString = stringHolder.toString()
    override def equals(ot: Any) : Boolean = {
      return stringHolder.equals(ot.asInstanceOf[Test].stringHolder)
    }

  }

  def main(args : Array[String]) : Unit = {
    val l1 = List(Test(new JStringHolder("a")), Test(new JStringHolder("b")))
    val l2 = List(Test(new JStringHolder("b")), Test(new JStringHolder("c")))
    println (l1.diff(l2))
    println (l1.intersect(l2))
    println (l1.union(l2))
  }
}

Ответы [ 4 ]

3 голосов
/ 17 ноября 2011

Проблема в том, что вы должны переопределить метод hashCode таким образом, чтобы два экземпляра показывали один и тот же hashCode, когда вы думаете, что они одинаковы.Только если hashCode одинаков, будет вызван метод equals, иначе два экземпляра не будут одинаковыми (по крайней мере в смысле List.diff и intersect).

Использование приведенного ниже кода приведет к результатуЯ хочу:

List(a)
List(b)
List(a, b, b, c)

А вот и используемый код:

package scalatest;

public class JStringHolder {
String s = null;

public JStringHolder(String newString){
    s = newString;
}

@Override
public String toString() {
    return s;
}

@Override
public boolean equals(Object obj) {
    return this.s.equals(((JStringHolder)obj).s);
}
@Override
public int hashCode() {
    return s.hashCode();
}
}

И код скала, который нужно выполнить:

package scalatest

object ListTest {

  trait AbstractTest 
  case class Test(stringHolder: scalatest.JStringHolder) extends AbstractTest {
    override def toString = stringHolder.toString()
    override def equals(ot: Any) : Boolean = {
      return stringHolder.equals(ot.asInstanceOf[Test].stringHolder)
    }
    override def hashCode() : Int = {
      stringHolder.hashCode()
    }       
  }

  def main(args : Array[String]) : Unit = {
    val l1 = List(Test(new JStringHolder("a")), Test(new JStringHolder("b")))
    val l2 = List(Test(new JStringHolder("b")), Test(new JStringHolder("c")))
    println (l1.diff(l2))
    println (l1.intersect(l2))
    println (l1.union(l2))
  }
}
1 голос
/ 16 ноября 2011

Я не совсем уверен: может быть, ошибка, если реализация diff? Использование устаревшего -- вместо diff на самом деле работает для меня. Set вместо List тоже работает.

У меня нет ответа (только предложение использовать Set в качестве обходного пути), но я добавляю сюда свои собственные тесты на случай, если они могут помочь кому-то еще вернуться с ответом:

// re-implementing JStringHolder in scala
// to show that this is not java-specific
class JStringHolder(val st: String) {
    override def equals(that: Any): Boolean = that match {
        case t: JStringHolder => this.st == t.st
        case _ => false
    }
}
case class Test(stringHolder: JStringHolder) {
    override def equals(that: Any) : Boolean = that match {
        case t: Test => this.stringHolder == t.stringHolder
        case _ => false
    }
}

теперь в REPL (scala 2.9.0.1):

scala> List(Test(new JStringHolder("a")), Test(new JStringHolder("b")))
res0: List[Test] = List(a, b)

scala> List(Test(new JStringHolder("c")), Test(new JStringHolder("b")))
res1: List[Test] = List(c, b)

scala> res0 diff res1
res2: List[Test] = List(a, b)

- устарела, но работает

scala> res0 -- res1
<console>:13: warning: method -- in class List is deprecated: use `list1 filterN
ot (list2 contains)` instead
       res0 -- res1
            ^
res3: List[Test] = List(a)

делать это с помощью фильтраНе, как подсказывает предупреждение об устаревании, тоже работает

scala> res0 filterNot (res1 contains )
res4: List[Test] = List(a)

Также показывает, что все работает с Set

scala> Set(Test(new JStringHolder("a")), Test(new JStringHolder("b")))
res0: scala.collection.immutable.Set[Test] = Set(a, b)

scala> Set(Test(new JStringHolder("b")), Test(new JStringHolder("c")))
res1: scala.collection.immutable.Set[Test] = Set(b, c)

scala> res0 diff res1
res2: scala.collection.immutable.Set[Test] = Set(a)

scala> res0 union res1
res3: scala.collection.immutable.Set[Test] = Set(a, b, c)

scala> res0 intersect res1
res4: scala.collection.immutable.Set[Test] = Set(b)
0 голосов
/ 17 ноября 2011
scala> object ListTest {
     | 
     |   trait AbstractTest 
     |   case class Test (stringHolder: JStringHolder) extends AbstractTest {
     |     override def toString = stringHolder.toString ()
     |     override def equals (ot: Any) : Boolean = {
     |       stringHolder.equals (ot.asInstanceOf [Test].stringHolder)
     |     }
     |   }
     | 
     |   def main (args : Array [String]) : Unit = {
     |     val a = Test (new JStringHolder ("a"))
     |     val b = Test (new JStringHolder ("b"))
     |     val c = Test (new JStringHolder ("c"))
     |     val l1 = List (a, b)
     |     val l2 = List (b, c)
     |     println (l1.diff (l2))
     |     println (l1.intersect (l2))
     |     println (l1.union (l2))
     |   }
     | }
defined module ListTest

scala>  ListTest.main (null) 
List(a)
List(b)
List(a, b, b, c)

Первый тест (JStringHolder ("b")) не == второй.

0 голосов
/ 16 ноября 2011

У вас нет большого выбора, кроме как инкапсулировать эти значения во что-то разумным equals методом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...