【问题标题】:Make this program more efficient?让这个程序更有效率?
【发布时间】:2014-03-14 06:49:19
【问题描述】:

只是好奇是否有人对使这个程序更简单有任何想法。它将数据库中的记录读入 ArrayList 并允许用户按状态搜索记录。它在大约 16000 毫秒内处理包含 100 万条记录的数据库。

import java.sql.*;
import java.util.*;
public class ShowEmployeeDB
{
public static void main(String args[])     
{
   ArrayList <String> Recs = new ArrayList <String>();
   String driverName = "sun.jdbc.odbc.JdbcOdbcDriver";
   String connectionURL = "jdbc:odbc:CitizensDB";  
   Connection con = null;    
   Statement  stmt = null;     
   String sqlStatement = "SELECT * FROM Citizens";
   ResultSet rs = null;       
   int r = 0;
   Scanner scan = new Scanner(System.in);
   String search = null;
   long starttime = System.currentTimeMillis();
   try 
   {   
       Class.forName(driverName).newInstance();  
       con = DriverManager.getConnection(connectionURL);
       stmt = con.createStatement();    
       rs = stmt.executeQuery(sqlStatement);  

       String ID = null;
       String Age = null;
       String State = null;
       String Gender = null;
       String Status = null;
       String record = null;
       while (rs.next())
       {
           for (int k = 1; k <= 1; ++k)
           {
               ID = rs.getString(k) + " ";
               for (int j = 2; j <= 2; ++j)
                   Age = rs.getString(j) + " ";
               for (int i = 3; i <= 3; ++i)
                   State = rs.getString(i).toUpperCase() + " ";
               for (int h = 4; h <= 4; ++h)
                   Gender = rs.getString(h) + " ";
               for (int g = 5; g <= 5; ++g)
                   Status = rs.getString(g) + " ";
           }//for
           record = ID + Age + State + Gender + Status;
           Recs.add(record);
           ++r;
       }//while
       rs.close();
       stmt.close();
       con.close();
   } catch (Exception ex) { ex.printStackTrace();  }

   String endtime = System.currentTimeMillis() - starttime + "ms";
   System.out.println(endtime);

   System.out.print("Enter A Search State: ");
   search = scan.nextLine().toUpperCase();

   Iterator<String> iter = Recs.iterator();
    while(iter.hasNext())
    {
        String s = iter.next();
        if (s.contains(search))
        {
            System.out.println(s);
        }
    }//while
} // main
} // ShowEmployeeBD

任何建议将不胜感激。提前谢谢!

【问题讨论】:

  • 我猜 16000 是一个巨大的时间量,我建议你让查询更快,然后来 java 部分。尝试在数据库端搜索的内容创建索引。还要寻找分页。
  • 通常的交易,你要求用户输入然后搜索数据库(利用索引)不要拉整个数据库并在java端搜索记录
  • 也; for (int j = 2; j &lt;= 2; ++j)??
  • 那些 for 循环是什么意思?
  • 这是 Stack Exchange Code Review 站点的问题。

标签: java jdbc arraylist performance


【解决方案1】:

如果不经常搜索,我建议在运行查询之前输入搜索字符串,以便搜索结果直接来自数据库。在这种情况下,您不必重复所有 100 万条记录。

【讨论】:

    【解决方案2】:

    直接在 DB 上执行搜索,而不是获取所有记录并通过 java 代码进行搜索。 此外,如果搜索是在多列上,则根据 ID 在单个位置在 DB 中准备元数据,元数据可以进一步用于获取与查询匹配的所需结果。

    【讨论】:

      【解决方案3】:
      • 将您的逻辑与技术内容分开。在这样的卷积中,很难运行单元测试或任何优化。
      • 当只询问一个值时,为什么需要 for 循环。
      • 使用 StringBuilder 代替字符串连接。
      • 使用 try-with 或将 close 语句放在 finally 子句中。
      • 不要初始化不需要的变量 (r)。
      • 用于每个语句。
      • 查询数据库,而不是结果集。
      • 调整您的数据库。
      • 如果您只搜索状态,请仅过滤这些状态,因此构建一个对象并比较状态而不是字符串包含的内容。
      • 比较在列表中存储字符串之前的状态。
      • 调整您的列表,因为它会随着 1Mio 记录不断增长。
      • 使用哈希集而不是数组列表。
      • 针对接口进行开发。

      一个更好的程序可能如下所示:

      import java.sql.Connection;
      import java.sql.Driver;
      import java.sql.DriverManager;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.util.HashSet;
      import java.util.Scanner;
      import java.util.Set;
      
      public class ShowEmployeeDB {
      
        private static final String DRIVERNAME = "sun.jdbc.odbc.JdbcOdbcDriver";
        private static final String CONNECTIONURL = "jdbc:odbc:CitizensDB";
      
        private static final String SELECT_CITIZENS = "SELECT * FROM Citizens";
      
        static {
          try {
            DriverManager.registerDriver((Driver) Class.forName(DRIVERNAME).newInstance());
          } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | SQLException e) {
            e.printStackTrace();
          }
        }
      
        public static void main(final String args[]) {
          System.out.print("Enter A Search State: ");
          searchRecords();
        }
      
        private static void searchRecords() {
          try(Scanner scan = new Scanner(System.in);) {
            final String state = scan.nextLine();
      
            final long starttime = System.currentTimeMillis();
            final Set<Record> records = searchRecordsByState(state);
            System.out.println(System.currentTimeMillis() - starttime + "ms");
      
            for(final Record r : records) {
               System.out.println(r);
            }
      
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      
        private static Set<Record> searchRecordsByState(final String stateToFilter) {
          final Set<Record> records = new HashSet<>();
          try(Connection con = DriverManager.getConnection(CONNECTIONURL);
              PreparedStatement stmt = con.prepareStatement(SELECT_CITIZENS);
              ResultSet rs = stmt.executeQuery(); ) {
      
            while(rs.next()) {
              final String state = rs.getString(3);
              if(state.equalsIgnoreCase(stateToFilter)) {
                final Record r = new Record(rs.getString(1), rs.getString(2), state, rs.getString(4), rs.getString(5));
                records.add(r);
              }
            }
          } catch (Exception ex) {
            ex.printStackTrace();
          }
          return records;
        }
      }
      
      class Record {
        String id, age, state, gender, status;
      
        public Record(String id, String age, String state, String gender, String status) {
          this.id = id;
          this.age = age;
          this.state = state;
          this.gender = gender;
          this.status = status;
        }
      
        public String getState() {
          return state;
        }
      
        @Override
        public String toString() {
          StringBuilder sb = new StringBuilder();
          sb.append(id).append(' ')
            .append(age).append(' ')
            .append(state).append(' ')
            .append(gender).append(' ')
            .append(status);
          return sb.toString();
        }
      }
      

      这是未经测试的,因为我没有手动拥有一百万个条目的数据库。

      但最好的办法是查询数据库并仅捕获您需要的那些条目。所以在你的声明中使用WHERE-clause。

      【讨论】:

      • 非常感谢。我会尝试运行它。我目前正在学习 Java 课程,在我发布这篇文章时,我们还没有学到你提到的大部分内容。
      猜你喜欢
      • 1970-01-01
      • 2012-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-07
      • 1970-01-01
      • 2019-12-11
      • 1970-01-01
      相关资源
      最近更新 更多