2008-12-15 48 views
5

Tôi đang nghĩ về một cái gì đó như thế này:Cách tốt nhất để lấy giá trị tối thiểu và tối đa từ danh sách Các giá trị so sánh có chứa giá trị null là gì?

public static <T extends Comparable<T>> T minOf(T...ts){   
    SortedSet<T> set = new TreeSet<T>(Arrays.asList(ts)); 
    return set.first(); 
} 

public static <T extends Comparable<T>> T maxOf(T...ts){ 
    SortedSet<T> set = new TreeSet<T>(Arrays.asList(ts)); 
    return set.last(); 
} 

Nhưng không phải là null an toàn, đó là điều mà tôi muốn quá.

Bạn có biết cách nào tốt hơn để giải quyết vấn đề này không?

EDIT:

Sau những ý kiến ​​tôi cũng đã cố gắng min():

public static <T extends Comparable<T>> T minOf(T...ts){   
    return Collections.min(Arrays.asList(ts), new Comparator<T>(){ 

     public int compare(T o1, T o2) { 
      if(o1!=null && o2!=null){ 
       return o1.compareTo(o2); 
      }else if(o1!=null){ 
       return 1; 
      }else{ 
       return -1; 
      } 
     }}); 
} 

Bạn nghĩ gì về điều đó?

+0

Đó là hiệu quả kể từ khi bạn cần O (n log n) so sánh, kể từ khi TreeSet hiệu quả sắp xếp các Bộ sưu tập, trong đó n so sánh đủ. Ngoài ra, bạn tạo ra rất nhiều rác không cần thiết (Arrays.asList tạo ra một bản sao của "ts", và TreeSet không phải là nhẹ, quá). – mfx

+0

Arrays.asList không tạo bản sao của mảng. –

+0

Có điều đó có hiệu quả, nhưng tại sao không khai báo và đặt tên cho bộ so sánh đó ở nơi có thể tái sử dụng? Sau đó, thay vì sử dụng hàm minOf này, chỉ cần gọi Collections.min chuẩn với bộ so sánh được đặt tên đó. Mã của bạn trở nên dễ đọc hơn nhiều bằng cách sử dụng các cuộc gọi thư viện chuẩn. – Pyrolistical

Trả lời

39

Có gì sai với Collections.max?

Và tại sao bạn quan tâm đến sự an toàn vô giá trị? Bạn có chắc chắn muốn cho phép các số không nằm trong Bộ sưu tập của mình không?

+0

Câu hỏi đặt ra là tối đa * và * phút. Collections.max() sẽ xem xét mọi phần tử. Sau đó, thực hiện Collections.min() một lần nữa sẽ xem xét mọi phần tử. Vì vậy, có thể sắp xếp một lần nhanh hơn. – Yetti99

+1

@ Yetti99 sắp xếp sẽ chậm hơn vì nó là 'O (n log n)' và 'max' +' min' là 'O (2n)'. Điều gì sẽ tốt hơn một chút là làm một vòng lặp đơn và cập nhật cả max và min trong đó. Và OP dường như không yêu cầu cả hai trong một hàm duy nhất. –

3

Nếu bạn thực sự cần loại trừ "null" khỏi kết quả, và bạn không thể ngăn không cho nó nằm trong mảng của bạn, thì có thể bạn chỉ cần lặp qua mảng với một vòng lặp đơn giản và theo dõi "min "và" tối đa "trong các biến riêng biệt. Bạn vẫn có thể sử dụng phương thức "compare()" trên mỗi đối tượng để so sánh nó với các giá trị "tối thiểu" và "tối đa" hiện tại của bạn. Bằng cách này, bạn có thể thêm mã của riêng bạn để kiểm tra các giá trị rỗng và bỏ qua chúng.

EDIT: đây là một số mã để minh họa những gì tôi đang nói đến. Thật không may có một trường hợp cạnh bạn cần phải xem xét - nếu tất cả các đối số được truyền vào là null thì sao? Phương pháp của bạn trở lại là gì?

public static <T extends Comparable<T>> T minOf(T...ts){ 
    T min = null; 
    for (T t : ts) { 
     if (t != null && (min == null || t.compareTo(min) < 0)) { 
      min = t; 
     } 
    } 
    return min; 
} 

public static <T extends Comparable<T>> T maxOf(T...ts){ 
    T max = null; 
    for (T t : ts) { 
     if (t != null && (max == null || t.compareTo(max) > 0)) { 
      max = t; 
     } 
    } 
    return max; 
} 
1

Bạn không nên thực hiện Comparable chấp nhận null, vì nó phá vỡ hợp đồng của giao diện.

Từ https://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html:

Note rỗng đó không phải là một thể hiện của bất kỳ lớp, và e.compareTo (null) nên ném một NullPointerException mặc dù e.equals (null) trả về false.

Thay vào đó, bạn phải tạo giao diện mới, ví dụ: ComparableNull thay thế.

Xem thêm:

Các vấn đề liên quan