【问题标题】:Finding partial duplicate values and keeping a specific查找部分重复值并保留特定的
【发布时间】:2013-09-04 09:13:23
【问题描述】:

我有一个包含一个值和另一个列表的列表,在本例中是一个带有相应站点列表的 trainNumber。但是有重复的 trainNumbers,它们可能有不同的车站。从这里我正在尝试创建一个新列表,以保留具有最多车站的 trainNumbers。

例如,如果我有一个列表,其中包含:

String trainNumber = 1,  List trainNumber = [Station1, Station3]
String trainNumber = 2,  List trainNumber = [Station1, Station2, Station3]  
String trainNumber = 3,  List trainNumber = [Station1, Station3]  
String trainNumber = 3,  List trainNumber = [Station3]

我希望新列表包含:

String trainNumber = 1, List trainNumber = [Station1, Station3]  
String trainNumber = 2, List trainNumber = [Station1, Station2, Station3]  
String trainNumber = 3, List trainNumber = [Station1, Station3]

我已经看到使用 Set 删除重复的列表项,但是我需要指定要保留的项。

HashSet<Trains> newList = new HashSet<Trains>();
    for(Trains train: trainOverview){
        String trainNumber = train.getTrainNumber();
        int stationSize = train.getStations().size();
        int largest = 0;
        for(Trains trainCopy: trainOverview){
            if(trainNumber.equals(trainCopy.getTrainNumber())){
                int stationCopySize = trainCopy.getStations().size();
                if(stationCopySize > largest) largest = stationCopySize;
            }
        }
        if(togSize >= largest){
            newList.add(tog);
        }
    }

    trainOverview.clear();
    trainOverview.addAll(newList);

现在这有点工作,但我发现它非常混乱。我正在使用 HashSet 删除具有相同数量站的重复项(这也会发生)。肯定有更好的方法来解决这个问题?

编辑:感谢您的回答,但我看到 put 方法替换了键的值。我的情况是,除了新的值之外,我还想保留第一次映射到 key(trainNumber) 的值(站)。

我以前从未使用过地图,但这是我的方法(不确定我是否正确使用它):

    Map<String, List<Station>> overview= new TreeMap<String, List<Station>>();
    for(Trains train: trainOverview){
        List<Stations> lista = overview.get(train.getTrainNumber());
        //Merge lists if the key already exists, and replace the old value with the merged list
        if(overview.containsKey(train.getTrainNumber())){
            Set setboth = new HashSet(lista);
            setboth.addAll(train.getStations());
            lista.clear();
            lista.addAll(setboth);
            overview.put(train.getTrainNumber(), lista);
        }
        //If no key exists, create a new entry
        else{
            overview.put(train.getTrainNumber(), train.getStations());
        }   
    }

【问题讨论】:

  • 创建从 trainNumbers 到一组车站的映射并填充它。

标签: java list duplicates hashset


【解决方案1】:

只需使用Map&lt;String, List&lt;Station&gt;&gt;,而不是有两个列表。 trainNumber 将是唯一键,您可以轻松地在地图的相应列表中添加或删除电台。

更新

正如@ipavlic 建议的那样,使用Map&lt;String, Set&lt;Station&gt;&gt;,因为集合不允许重复元素。

更新2

这里有一个小例子,有一些 cmets。该示例向您展示了如何使用与集合相结合的地图。您应该将其以 1:1 的比例复制到您的代码中,因为这不是面向对象的方法。地图应该封装在某个对象中。

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

public class MapSetExample
{
  public static void main(String[] args)
  {
    Map<String, Set<String>> map = new HashMap<String, Set<String>>();
    System.out.println("ADDED = " + add(map, "Train1", "Station1"));
    System.out.println("ADDED = " + add(map, "Train1", "Station2"));
    System.out.println("ADDED = " + add(map, "Train1", "Station1"));

    System.out.println("Stations of Train1 = " + map.get("Train1"));

  }

  private static boolean add(Map<String, Set<String>> map, String key, String station) {
    Set<String> set = map.get(key);

    /* If map.get() returns null, that means there is no set
     * in the map associated with given key.
     * 
     * In that case we create a new set.
     * 
     * If there is already a set, we use that one.
     */
    if (set == null) {
      set = new TreeSet<String>();
      map.put(key, set);
    }
    /* False if station is already in set. At this point you could also delete sth. etc. */
    boolean success = set.add(station);
    return success;
  }
}

输出

ADDED = true
ADDED = true
ADDED = false
Stations of Train1 = [Station1, Station2]

【讨论】:

  • 更好的是,列一个集合。
  • 考虑到火车站,Set 可能不是最好的主意,因为它不关心火车停在那里的顺序
  • 从 OP 发布的示例中,他按编号对电台进行了排序,因此他可以使用 TreeSet。但是你说得对,如果元素的顺序有语义,那么他最好使用列表。
  • 谢谢,这似乎有效。但是,当将旧 Map 值与新值结合时,我遇到了问题。我试图组合没有重复值的列表(如您在我的编辑中所见)。但我得到了重复的电台。
  • 我为您添加了一些示例代码,展示了如何将地图和集合作为值一起处理(您也可以将此方法用于列表、其他地图等)。
【解决方案2】:

我认为Map&lt;String, Set&lt;Station&gt;&gt; 会更好。 trainNumber 作为唯一键,Set 用于站点以避免重复。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-30
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-19
    • 2010-12-15
    相关资源
    最近更新 更多