如何在JTable中对单列LocalDateTime格式的数据正确排序?
Great job getting this working with a custom Comparator on the TableRowSorter—that's a solid approach for cases where your table model is holding string representations of dates. Let's break down some improvements you can make to make this code more robust, efficient, and clean:
1. Reuse the DateTimeFormatter
Right now, you're creating a new DateTimeFormatter instance every time the compare method runs. Since your date pattern is fixed, you can initialize it once as a static final variable outside the comparator to avoid unnecessary object creation:
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.uuuu HH:mm:ss"); // Then in your comparator setup: sorter.setComparator(columnIndexToSort, new Comparator<String>() { @Override public int compare(String o1, String o2) { LocalDateTime ldt1 = LocalDateTime.parse(o1, DATE_FORMATTER); LocalDateTime ldt2 = LocalDateTime.parse(o2, DATE_FORMATTER); return ldt1.compareTo(ldt2); } });
2. Handle Invalid Date Strings
If any cell in your date column has a string that doesn't match the dd.MM.uuuu HH:mm:ss pattern, LocalDateTime.parse() will throw a DateTimeParseException, which will crash the sorting operation. Add error handling to define how invalid dates should be ordered—for example, pushing them to the end:
sorter.setComparator(columnIndexToSort, new Comparator<String>() { @Override public int compare(String o1, String o2) { try { LocalDateTime ldt1 = LocalDateTime.parse(o1, DATE_FORMATTER); LocalDateTime ldt2 = LocalDateTime.parse(o2, DATE_FORMATTER); return ldt1.compareTo(ldt2); } catch (DateTimeParseException e) { // Define behavior for invalid dates boolean o1Invalid = o1 == null || !o1.matches("\\d{2}\\.\\d{2}\\.\\d{4} \\d{2}:\\d{2}:\\d{2}"); boolean o2Invalid = o2 == null || !o2.matches("\\d{2}\\.\\d{2}\\.\\d{4} \\d{2}:\\d{2}:\\d{2}"); if (o1Invalid && o2Invalid) return 0; // Treat both as equal return o1Invalid ? 1 : -1; // Invalid dates go last } } });
3. Simplify with Lambdas
Since Java 8, you can replace the anonymous Comparator class with a lambda expression to make the code more concise without losing clarity:
sorter.setComparator(columnIndexToSort, (o1, o2) -> { try { LocalDateTime ldt1 = LocalDateTime.parse(o1, DATE_FORMATTER); LocalDateTime ldt2 = LocalDateTime.parse(o2, DATE_FORMATTER); return ldt1.compareTo(ldt2); } catch (DateTimeParseException e) { boolean o1Invalid = o1 == null || !o1.matches("\\d{2}\\.\\d{2}\\.\\d{4} \\d{2}:\\d{2}:\\d{2}"); boolean o2Invalid = o2 == null || !o2.matches("\\d{2}\\.\\d{2}\\.\\d{4} \\d{2}:\\d{2}:\\d{2}"); if (o1Invalid && o2Invalid) return 0; return o1Invalid ? 1 : -1; } });
4. Align Table Model with Actual Data Type (Cleaner Long-Term Fix)
Your initial attempt to use getColumnClass() to return LocalDateTime.class didn't work because your table model was still returning String values from getValueAt(). If you can modify your TableModel to store and return LocalDateTime objects directly (instead of strings), you won't need a custom comparator at all—TableRowSorter will automatically use the natural ordering of LocalDateTime:
@Override public Class<?> getColumnClass(final int columnIndex) { if (getColumnName(columnIndex).equals("Datecolumn")) { return LocalDateTime.class; } // Fallback logic for other columns try { return getValueAt(0, columnIndex).getClass(); } catch (Exception e) { return String.class; } } // Update getValueAt() to return LocalDateTime for the date column @Override public Object getValueAt(int rowIndex, int columnIndex) { if (getColumnName(columnIndex).equals("Datecolumn")) { // Parse your stored string once into LocalDateTime String dateStr = yourDataStore.get(rowIndex).getDateString(); return LocalDateTime.parse(dateStr, DATE_FORMATTER); } // Return other values as before return yourDataStore.get(rowIndex).getColumnValue(columnIndex); } // Then sorting becomes as simple as: table.setAutoCreateRowSorter(true);
This approach keeps your data model more type-safe and avoids repeated string parsing during sorting.
内容的提问来源于stack exchange,提问作者Toni

