【问题标题】:Most efficient way to eliminate repeating entries消除重复输入的最有效方法
【发布时间】:2019-12-24 11:35:37
【问题描述】:

我想将信息存储在 ArrayList 中。我正在从 csv 文件中获取数据,但有相同的数据,我想消除它们。最有效的方法是什么?我考虑了两种方法:将所有数据添加到 Set 并将其转换为 ArrayList。将它们添加到 ArrayList 中,同时检查它不包含相同的数据。这是我的代码:

public static void sanitization(String file_path) throws FileNotFoundException, IOException {

    File file = new File(file_path);
    BufferedReader reader = new BufferedReader(new FileReader(file)); //read the csv file

    Set<Flight> flights_set = new HashSet<>(); //All valid flights will be added to set in order to prevent from adding same flights.

    String[] split = new String[31];
    String st;

    while ((st = reader.readLine()) != null) {
        split = st.split(",", -2);
        flights_set.add(new Flight(split[4], split[5], Integer.valueOf(split[11]), split[7], split[8], Integer.valueOf(split[0]), Integer.valueOf(split[1]), Integer.valueOf(split[2])));
    }

    //Second possible way
    /*while ((st = reader.readLine()) != null) {
        split = st.split(",", -2);
        Flight f=new Flight(split[4], split[5], Integer.valueOf(split[11]), split[7], split[8], Integer.valueOf(split[0]), Integer.valueOf(split[1]), Integer.valueOf(split[2]));

        if(!flights_arraylist.contains(f))
            flights_arraylist.add(f);
    }*/

    ArrayList<Flight> flights_arraylist = new ArrayList<>(flights_set);

}

class Flight implements Comparable<Flight> {

//All necessary information
public String airline;
public String flight_number;
public Integer departure_delay;
public String origin_airport_name;
public String destination_airport_name;
public Integer year;
public Integer month;
public Integer day;

//Constructor
public Flight(String airline, String flight_number, Integer departure_delay, String origin_airport_name, String destination_airport_name, Integer year, Integer month, Integer day) {
    this.airline = airline;
    this.flight_number = flight_number;
    this.departure_delay = departure_delay;
    this.origin_airport_name = origin_airport_name;
    this.destination_airport_name = destination_airport_name;
    this.year = year;
    this.month = month;
    this.day = day;
}

public Flight() {

}

//Flight is bigger if its departure delay is bigger
public int compareTo(Flight o) {
    if (this.departure_delay > o.departure_delay) return 1;
    else if (this.departure_delay < o.departure_delay) return -1;
    else return 0;
}

@Override
public boolean equals(Object obj) {
    Flight f = (Flight) obj;

    if ((this.airline.equals(f.airline)) && (this.flight_number.equals(f.flight_number)) && (this.departure_delay.equals(f.departure_delay)) && (this.origin_airport_name.equals(f.origin_airport_name)) && (this.destination_airport_name.equals(f.destination_airport_name)) && (this.year.equals(f.year)) && (this.month.equals(f.month)) && (this.day.equals(f.day))) {
        return true;
    }
    return false;

}

@Override
public int hashCode() {
    return 0;
}

@Override
public String toString() {
    return this.airline + " " + this.flight_number + " " + this.departure_delay;
}

}

这也是我的第一个问题,如果我犯了任何错误请警告我

【问题讨论】:

  • 你可以使用 Set ,有没有必要使用 ArrayList ?
  • 让您的Flight 对象计算正确的哈希码是一种很好的形式。您的 Java IDE 可能能够为您生成合适的 hashCode() 方法,或者您可以使用 Objects.hash 来简化自己编写的任务。当HashSets 和HashMaps 中的所有对象都具有相同的哈希码时,它们可能可能遭受性能下降。
  • 使用Set 而不是ArrayList 是一种非常好的方法。唯一需要考虑的是集合成员是否需要插入顺序。
  • @MdFaraz 我稍后会对它们进行排序。

标签: java performance arraylist set


【解决方案1】:

您可以使用流,以下是列表的示例方法。

首先将所有元素添加到列表中,然后使用流并收集不同的元素并在同一列表中更新。

例子:

List<String> strList = new ArrayList<String>();
strList.add("Alpha");
strList.add("Beta");
strList.add("Charlie");
strList.add("Delta");
strList.add("Delta");
strList.add("Delta");

strList = strList.stream().distinct().collect(Collectors.toList());
System.out.println("Without duplicate");
strList.forEach(System.out::println);

输出:

Without duplicate
Alpha
Beta
Charlie
Delta

【讨论】:

    【解决方案2】:

    来自 java.util.Set#add 的 javadoc:@return 如果此 set 尚未包含指定元素,则返回 true。 此外,对于此答案,请注意 BufferedReader 提供了 lines 方法,该方法返回文件中的字符串流。 知道这一点你可以写这样的东西:

        List<Flight> result;//list of your choice;
        Set<Flight> flightSet; //set of your choice;
        BufferedReader reader; // init bufferedReader
        reader.lines()
                .forEach(line -> {
                    Flight flight;//transform into object;
                    if (flightSet.add(flight)) {
                        result.add(flight);
                    }
                });
    

    或者,完全使用流,收集不同的映射线:

    BufferedReader reader; // init bufferedReader
    reader.lines()
                .map(line->new Flight(/*... args*/))
                .distinct()
                .collect(Collectors.toList())
    

    【讨论】:

      【解决方案3】:

      为避免重复,您最终需要在可用数据中进行搜索。

      平均而言,HashSet.contains() 运行时间为O(1)

      然而,在内部,ArrayList 使用 indexOf(object) 方法来检查对象是否在列表中。 indexOf(object) 方法迭代整个数组,并用 equals(object) 方法比较每个元素。

      回到复杂性分析,ArrayList.contains() 方法需要O(n) 时间。

      使用SET存储不重复,然后转换为List是最有效的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-22
        • 1970-01-01
        • 2017-10-18
        • 2018-04-02
        • 2015-08-02
        • 2011-08-14
        相关资源
        最近更新 更多