番石榴的Sets.Intersection方法行为不端

时间:2014-01-13 07:26:59

标签: java guava

我有一个场景,其中,我需要根据特定字段(在这种情况下只有颜色)从集合中包含的对象中找到两个集合的交集。

因此,我试图找到一个交集,减去两个集合(使用比较器,使用对象的颜色来决定2个汽车对象的相等性),使用谷歌的番石榴。但奇怪的是,交叉点B不等于B交点A.

请帮我找出出错的地方。 为什么A交点B不等于B交点A?我只对交叉路口感兴趣。

   public class Car {

   public String id;
     public String color;
   public String getId() {
          return id;
   }
   public void setId(String id) {
          this.id = id;
   }
   public String getColor() {
          return color;
   }
   public void setColor(String color) {
          this.color = color;
   }


   @Override
   public int hashCode() {
          final int prime = 31;
          int result = 1;
          result = prime * result + ((color == null) ? 0 : color.hashCode());
          result = prime * result + ((id == null) ? 0 : id.hashCode());
          return result;
   }
   @Override
   public boolean equals(Object obj) {
          if (this == obj)
                 return true;
          if (obj == null)
                 return false;
          if (getClass() != obj.getClass())
                 return false;
          Car other = (Car) obj;
          if (color == null) {
                 if (other.color != null)
                       return false;
          } else if (!color.equals(other.color))
                 return false;
          if (id == null) {
                 if (other.id != null)
                       return false;
          } else if (!id.equals(other.id))
                 return false;
          return true;
   }
   public Car(String id, String color) {
          super();
          this.id = id;
          this.color = color;
   }
   public Car() {
          super();
   }


  }

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

import com.google.common.collect.Sets;


 public class Tester {

   public static void main(String[] args) {

          final Set<Car> first = new TreeSet<Car>( new Comparator<Car> (){
                 public int compare( final Car o1, final Car o2 ){
                  return comp(o1.getColor(), o2.getColor() );  
              }
          } );
          first.add(new Car("1","blue"));
          first.add(new Car("2","green"));
          first.add(new Car("3","red"));

          final Set<Car> second = new TreeSet<Car>( new Comparator<Car> (){
                 public int compare( final Car o3, final Car o4 ){
                  return comp1(o3.getColor(), o4.getColor() );  
              }
          } );
          second.add(new Car("4","black"));
          second.add(new Car("5","green"));
          second.add(new Car("6","blue"));
          second.add(new Car("7","red"));

          final Set<Car> intersection1 = Sets.intersection( first, second );
          System.out.println("intersection1 size = "+intersection1.size());
          for(Car carr : intersection1){
                 System.out.println("carr.id ="+carr.id+" carr.color ="+carr.color);
          }
          System.out.println();
          final Set<Car> intersection2 = Sets.intersection( second, first);
          System.out.println("intersection2 size = "+intersection2.size());
          for(Car carr : intersection2){
                 System.out.println("carr.id ="+carr.id+" carr.color ="+carr.color);
          }
          System.out.println();

          final Set<Car> Pure1 = Sets.difference(first, second);
          System.out.println("Pure1 size = "+Pure1.size());
          for(Car carr : Pure1){
                 System.out.println("carr.id ="+carr.id+" carr.color ="+carr.color);
          }
          System.out.println();

          final Set<Car> Pure2 = Sets.difference(second, first);
          System.out.println("Pure2 size = "+Pure2.size());
          for(Car carr : Pure2){
                 System.out.println("carr.id ="+carr.id+" carr.color ="+carr.color);
          }
          System.out.println();

    }
    static int comp(String a, String b ){
          if(a.equalsIgnoreCase(b)){
                 return 0;
          }
          else 
                 return 1;
   }
   static int comp1(String a, String b ){
          if(a.equalsIgnoreCase(b)){
                 return 0;
          }
          else 
                 return 1;
   }

 }

输出:

intersection1 size = 3
carr.id =1 carr.color =blue
carr.id =2 carr.color =green
carr.id =3 carr.color =red

intersection2 size = 2
carr.id =5 carr.color =green
carr.id =7 carr.color =red

Pure1 size = 0

Pure2 size = 2
carr.id =4 carr.color =black
 carr.id =6 carr.color =blue

1 个答案:

答案 0 :(得分:3)

comp的实现不正确,并且您的比较器不满足他们的合同,因此您可以从TreeSet获得未定义和不可预测的行为。这与Guava的Sets.intersection方法无关。

Comparator.compare的规范说:

  

比较其订单的两个参数。当第一个参数小于,等于或大于第二个参数时,返回负整数,零或正整数。

... Comparator不做的事。

最简单的解决方法可能是使用

new Comparator<Car>(){
    public int compare(Car o1, Car o2) {
        return o1.getColor().compareToIgnoreCase(o2.getColor());
    }
}