【问题标题】:Correct way of looping to avoid creating double objects正确的循环方式避免创建双重对象
【发布时间】:2012-11-28 23:10:35
【问题描述】:

我有一个从数据库收集信息的程序。

在我之前的问题中,我询问了一个执行,其中一个响应让我重新思考了我的循环的想法链接到旧问题:ConcurrentModificationExecption

所以这是我从数据库中收集的大量信息的背景,其中一个信息是存储在我的数据库中的呼叫类型的名称,例如:邮件、电话等。将是不同类型的联系信息(我们称之为 CallQueues)

由于我提取的信息已超过几天,因此许多呼叫类型都会重复。以下是数据库中一行的外观示例:

ID 姓名 日期 NoC NoAC

1 邮件 2012-11-27 3 3

其中 NoC = 调用次数 NoAC = 已接电话数。

现在我的问题。

我最初的想法是遍历队列列表并查看名称是否重新出现,但这不起作用,因为我无法在循环时更改列表。所以这是我从while循环开始的新想法,我想知道的是:这是在这种情况下避免重复的最好方法吗?如果不是,请你解释一下我应该怎么做?

** 代码**

    ArrayList<CallQueue> queues = new ArrayList<>();
    while (query.next()) {

        boolean isNew = true;
        if (!queues.isEmpty()) {
            for (CallQueue callQueue : queues) {
                if (callQueue.getType().equals(query.getString("NAME"))) {
                    double decimalTime = query.getDouble("DATE");
                    int hourOfDay = (int)Math.round(24 * decimalTime);
                    int callAmount = query.getInteger("NoC");
                    if (hourOfDay > 19) {
                        hourOfDay = 19;
                    }

                    callQueue.addCallsByTime(hourOfDay, callAmount);
                    isNew = false;
                }else {
                    isNew = true;
                }
            } 

            /* Out side the foreach loop, checks if the boolean isNew is true if it is create a new object and insert into the list*/
            if (isNew) {
                String queueName = query.getString("NAME");
                if (!queueName.equalsIgnoreCase("PrivatOverflow")) {
                    CallQueue cq = new CallQueue(query.getString("NAME"));
                    double decimalTime = query.getDouble("DATE");
                    int hourOfDay = (int)Math.round(24 * decimalTime); 
                    int callAmount = query.getInteger("NoC");
                    if (hourOfDay > 19) {
                        hourOfDay = 19;
                    }
                    cq.addCallsByTime(hourOfDay, callAmount);
                    queues.add(cq);
                }
            }
            /* if queues is empty which it will be the first time*/
        }else {
            String queueName = query.getString("NAME");
            if (!queueName.equalsIgnoreCase("PrivatOverflow")) {
                CallQueue cq = new CallQueue(query.getString("NAME"));
                double decimalTime = query.getDouble("DATE");
                int hourOfDay = (int)Math.round(24 * decimalTime); 
                int callAmount = query.getInteger("NoC");
                if (hourOfDay > 19) {
                    hourOfDay = 19;
                }
                cq.addCallsByTime(hourOfDay, callAmount);
                queues.add(cq);

            }

        }
    }

【问题讨论】:

    标签: java object loops


    【解决方案1】:

    说明

    不要将queues 设为ArrayList,将其设为HashSet 或其他某种Set。这将在 O(1) 时间而不是 O(n) 时间内为您捕获重复项。完成加载查询后,您始终可以将数据从 HashSet 中取出并将其放入 ArrayList 以供将来使用(这样做的另一个好处是您将确切知道要制作 @987654327 的时间@. 这将是一个 O(n) 副本,但您只需执行一次,而不是像其他方式那样每次都执行。

    要正确执行此操作,您可能必须覆盖 CallQueue.hashCode().equals(),但这很简单,只需返回 String name 字段的 .hashCode().equals() 方法即可。

    错误??

    顺便说一句,我假设queryjava.sql.ResultSet,但ResultSet 没有getInteger,它有getInt。你的代码编译了吗?

    代码

    这是代码,看看我的意思:

    HashMap<String, CallQueue> queues = new HashMap<String, CallQueue>(); 
    
    while (query.next()) {
      if (!queues.isEmpty()) {
        if (queues.containsKey(query.getString("NAME"))) {
          CallQueue oldQueue = queues.get(query.getString("NAME"));
          double decimalTime = query.getDouble("DATE");
          int hourOfDay = (int)Math.round(24 * decimalTime);
          int callAmount = query.getInt("NoC");
          if (hourOfDay > 19) {
            hourOfDay = 19;
          }
    
          oldQueue.addCallsByTime(hourOfDay, callAmount);
        } else {
          String queueName = query.getString("NAME");
          if (!queueName.equalsIgnoreCase("PrivatOverflow")) {
            CallQueue cq = new CallQueue(query.getString("NAME"));
            double decimalTime = query.getDouble("DATE");
            int hourOfDay = (int)Math.round(24 * decimalTime); 
            int callAmount = query.getInt("NoC");
            if (hourOfDay > 19) {
              hourOfDay = 19;
            }
            cq.addCallsByTime(hourOfDay, callAmount);
            queues.put(query.getString("NAME"), cq);
          }
        }
      }
    }
    
    // you could return this if you just want a collection...
    Collection<CallQueue> values = queues.values();
    
    // Or this if you MUST have an ArrayList...
    return new ArrayList(values);
    

    【讨论】:

    • CallQueue 对象已经包含一个 Hashmap,我将用于以后的目的。哈希集由两个整数时间 + 数据组成
    【解决方案2】:

    您也可以在 sql 中使用 group by name 或 select distinct 来执行此操作。

    【讨论】:

    • 请详细说明我在我的 SQL 语句中使用 group by 但我看不出这如何帮助我避免由于日期不同而产生的重复,即:2012-11-27 是与 2012 年 11 月 23 日不同,在这几天之间有一些我需要的数据
    猜你喜欢
    • 2011-01-27
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-29
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    相关资源
    最近更新 更多