【问题标题】:Remove some repeated items in a List [duplicate]删除列表中的一些重复项[重复]
【发布时间】:2017-12-15 22:00:57
【问题描述】:

我正在使用这样的 java 对象:

public class GeoName {
   private String country;
   private String city;
   private float lat;
   private float lon;
}

我收到一份 GeoName 列表,我想尽可能高效地删除列表中同一国家/地区的重复城市。我的意思是,如果我收到以下列表:

Madrid, Spain, ...
London, England, ...
Madrid, Mexico, ...
London, England, ...
Paris, France, ...
Madrid, Spain, ...

我想删除重复的项目(城市+国家),直到列表如下:

Madrid, Spain, ...
London, England, ...
Madrid, Mexico, ...
Paris, France, ...

我正在努力,但我不知道该怎么做!

有什么想法吗?

谢谢!

PS:我不能使用 Set 集合,因为我发现一个城市的名称在一个经纬度不同的国家重复出现(这很奇怪,但它们确实存在)。所以它不会是套装上完全平等的物品

【问题讨论】:

  • 嗨,到目前为止,您尝试了什么?
  • 使用Set 而不是数组。
  • 我昨天回答了一个这样的问题,它被删除了T_T
  • 设置不可行,因为我发现同一个国家的一些城市有不同的经纬度(纬度、经度属性)。
  • 您可以使用一个哈希集,并为该对象定义 hashCode 以仅使用国家和城市名称吗?

标签: java list collections unique items


【解决方案1】:

您可以为只考虑国家和城市的GeoName 实现 hashCode() 和 equals()。

@Override
public boolean equals(Object o) {
    if (this == o)
        return true;
    if (o == null || getClass() != o.getClass())
        return false;

    GeoName geoName = (GeoName) o;

    if (!country.equals(geoName.country))
        return false;
    return city.equals(geoName.city);
}

@Override
public int hashCode() {
    int result = country.hashCode();
    result = 31 * result + city.hashCode();
    return result;
}

之后,您可以使用HashSet() 将所有地理名称放入其中。重复项将被自动高效地整理出来。

    List<GeoName> myInputList = ...;
    Set<GeoName> geoSet = new HashSet<>(myInputList);

【讨论】:

    【解决方案2】:

    应该这样做:

    我使用修改后的 .equals 方法创建您的类,然后使用所述 .equals 方法检查该类的 2 个测试实例是否相同。

    class GeoName {
       private String country;
       private String city;
    
       public GeoName(String country, String city) {
           this.country = country;
           this.city = city;
       }
    
        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final GeoName other = (GeoName) obj;
            if (!Objects.equals(this.country, other.country)) {
                return false;
            }
            if (!Objects.equals(this.city, other.city)) {
                return false;
            }
            return true;
        }
    }
    

    测试类:

    public class Cities {
        public static void main(String[] args) {
              // ArrayList<GeoName> geos = new ArrayList<>(); 
    
              GeoName test = new GeoName("Madrid", "Spain");
              GeoName test1 = new GeoName("Madrid", "Mexico");
    
                if (test.equals(test)) {
                    System.out.println("True 1");
                }
    
                if (test.equals(test1)) {
                    System.out.println("True 2");
                }
        }
    }
    

    输出:

    True 1
    

    然后您将遍历数组并检查所有数组,如果不存在则将其添加到数组中,我将其留给您。

    【讨论】:

    • 你不应该这样做。您必须将每个实例与另一个实例进行比较,从而导致O(n^2) 复杂性。使用 HashSet 更通用、更简洁,并且在 O(n) 中运行。
    • 小规模也可以。
    【解决方案3】:

    这是一个完整的例子:

    import java.util.HashSet;
    import java.util.Objects;
    import java.util.Set;
    
    public class GeoName {
       private String country, city;
       private float lat, lon;
    
       public GeoName(String country, String city, float lat, float lon){
           this.country = country;
           this.city = city;
           this.lat = lat;
           this.lon = lon;
       }
    
       @Override
       public boolean equals(Object other){
          if(other==null) return false;
          if(other instanceof GeoName){
            return ((GeoName)other).city.equals(this.city) &&
                   ((GeoName)other).country.equals(this.country);
          }
          return false;   
        }
    
        @Override
        public String toString(){
            return city + ", "+ country +
                   ", " + lat +", " + lon;
        }
    
    
        @Override
        public int hashCode(){
           return Objects.hash(country, city);
    
        }
    
        // to test
        public static void main(String[] args) {
            List<GeoName> list = new ArrayList<>();
    
            list.add(new GeoName("Madrid", "Spain",1.0f, 2.0f));
            list.add(new GeoName("England", "London",3.0f, 4.0f));
            list.add(new GeoName("England", "London",3.0f, 4.0f));
            list.add(new GeoName("France", "Paris",7.0f, 9.0f));
            list.add(new GeoName("Mexico", "Madrid",9.0f, 10.0f));
    
            Set<GeoName> set = new HashSet<>(list);
    
            for(GeoName geoName : set){
                System.out.println(geoName);
            }          
        }    
    }
    

    输出:

    London, England, 3.0, 4.0
    Madrid, Mexico, 9.0, 10.0
    Paris, France, 7.0, 9.0
    Spain, Madrid, 1.0, 2.0
    

    【讨论】:

      【解决方案4】:

      要从自定义数据(例如 GeoName )集合中删除重复条目,请实现 equals() 和 hashcode() 方法。

      然后将数据添加到 Set 中以删除重复条目。

      根据您的逻辑实现 equals() 和 hashcode() 以识别重复数据。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-09-30
        • 2011-10-04
        • 2020-03-16
        • 2011-10-07
        • 2011-07-23
        • 2013-05-28
        • 2020-04-22
        • 1970-01-01
        相关资源
        最近更新 更多