2009-04-29 34 views
5

Với kiểu Integer bạn có thể làm điều này:Java Generics và Infinity (tương đương)

int lowest = Integer.MIN_VALUE; 

Tôi có thể làm gì nếu tôi sử dụng Generics?

K lowest = <...>; 

Tôi cần điều này để thực hiện điều gì đó tương tự như PriorityQueue. Tôi có quyền truy cập vào nút mà tôi muốn xóa khỏi hàng đợi nhưng không phải là nút.

1. I need to make it the min by decreasing the key of that node, 
2. And then remove the min. 

Tôi bị kẹt ở bước đầu tiên. Điều duy nhất tôi có thể làm là đặt khóa của nút thành min hiện tại. Không chắc là đủ rồi.

+0

Bạn có thể cung cấp một số mã mẫu minh họa cách bạn muốn sử dụng K không? –

+0

Bạn có thể xây dựng một chút không? Một số mã có liên quan sẽ tốt đẹp. –

+0

Ngẫu nhiên, các phiên bản đối tượng của các chữ số đều mở rộng java.lang.Number. Thật không may, số không có bất cứ điều gì như getMaximumValue(). – Powerlord

Trả lời

4

này không có ý nghĩa gì ...

Cho rằng bạn không biết những gì K là tại thời điểm đó, (ví dụ: Bạn đang thực hiện nó quát ... duh!), Bạn có thể không chỉ định một min/max ràng buộc cho nó.

trong trường hợp K có thể là một int, long, chuỗi HOẶC đối tượng, bạn có thể không hợp lý đoán sử dụng

Integer.MIN_VALUE, "" OR NULL.

Tôi đoán những gì bạn đang tìm kiếm là K.MIN_VALUE_OF_EVENTUAL_TYPE nhưng điều đó không tồn tại.

+2

Đây có thể là một người nào đó đến từ nền C++, nơi nó tầm thường khi chỉ sử dụng numeric_limits :: max và numeric_limits :: min. Điều này cho phép bạn viết mã xử lý ký tự, tăng gấp đôi, int, 64 bit int, hoặc thậm chí các lớp số tùy chỉnh. – Eclipse

+0

Tôi tình cờ gặp vấn đề này trong khi tìm kiếm cùng một ý tưởng và đây là trường hợp sử dụng của tôi: 1. Tôi có một giao diện với phương thức sau đây: 'Comparable getGroupIndex (String groupName)' phương thức này trả về 'null' nếu' groupName' là không biết. 2. Trong một lớp mà tôi gọi phương thức ở trên, nếu giá trị trả về là 'null' thì tôi muốn đặt nó ở cuối danh sách (coi nó là nếu nó trả về giá trị tối đa có thể so sánh). Thay vào đó, tôi sẽ giải quyết điều này bằng cách trả lại giá trị tối đa thay vì null nhưng chỉ muốn làm sáng tỏ một số trường hợp sử dụng. – mwakerman

1

Uh không phụ thuộc vào loại K này?

Điểm Generics là K có thể là bất kỳ loại (hoặc bất kỳ lớp con của một loại nhất định); để có thể gọi các phương thức trên K hoặc truy cập các thuộc tính của nó, bạn cần phải hạn chế các ràng buộc kiểu của nó với các ký tự đại diện.

+0

Vâng, K có thể so sánh được. –

+1

Nó có vẻ như một điều hợp lệ để muốn - nếu đó là một int, tôi muốn giá trị thấp nhất, nhưng nếu nó là một dài, tôi muốn giá trị dài nhất thấp nhất. Tôi không chắc chắn có một câu trả lời đơn giản mặc dù. Nếu bạn không sử dụng Generics (chỉ cần chuyển qua một số hoặc so sánh), bạn có thể sử dụng sự phản chiếu để giải quyết hầu hết các trường hợp (các số thường có cùng trường .MIN_VALUE mà tôi nghĩ) –

+0

So sánh với cái gì? Nó chỉ có thể so sánh với các K khác mà bạn không biết. –

4

Không có hình thức chung là MIN_VALUE hoặc MAX_VALUE cho tất cả các loại có thể so sánh.

Hãy suy nghĩ về lớp học Time có thể so sánh được. Không có MAX_VALUE cho Thời gian mặc dù nó có thể so sánh được.

1

chỉ vì một đối tượng có thể so sánh không có nghĩa là nó phải có giá trị tối thiểu. Lý do int có giá trị nhỏ nhất là - (2^(31)) là vì bạn cần 1 bit cho một dấu, vì vậy 2^31 là số nguyên lớn nhất (hoặc nhỏ nhất) có thể được lưu trữ. Đối với những thứ như chuỗi, nó không có ý nghĩa gì vì không có chuỗi lớn nhất/nhỏ nhất có thể, nó là bộ nhớ bị ràng buộc.

+0

Chắc chắn có một chuỗi nhỏ nhất có thể: "". Nó chỉ là bộ nhớ lớn nhất bị ràng buộc, – Eclipse

+0

Các quy tắc sắp xếp theo ngữ cảnh. Tôi có thể dễ dàng xác định một đơn hàng đặt các chuỗi rỗng cuối cùng. – erickson

1

Bạn có thể phải tạo giao diện "IInfinity" và có K mở rộng IInfinity và IInfinity để có phương thức "getInfinityValue()" và sau đó bao bọc/mở rộng Số nguyên, Đôi, BigDecimal, v.v. trong một lớp thực hiện IInfinity ... và ugh!

1

Về cơ bản bạn muốn bất kỳ loại K nào để triển khai một số hàm tĩnh nói thấp nhất và cao nhất tuân theo các đặc tính toán học chuẩn.

Tôi giả định rằng đối với cảm giác thấp nhất (hoặc cao nhất) này có thể sử dụng được, bạn sẽ muốn bất kỳ đối tượng Comparable nào có các phương thức này. (hoặc các trường tĩnh). Nếu bạn chỉ quan tâm đến các đối tượng tùy chỉnh của riêng mình, cách để làm điều này sẽ là có mọi thứ kế thừa từ một kiểu dữ liệu trừu tượng khai báo các trường tĩnh cho MINVALUE và MAX_VALUE và sau đó các biến kiểu của bạn sẽ là.Nếu bạn cần chức năng này cho các lớp khác, bạn sẽ cần cre4ate một số loại băm bên ngoài theo dõi các thuộc tính này cho các lớp khác nhau (nhưng điều đó sẽ trở nên khá xấu)

4

Tôi đang cố tưởng tượng kịch bản nào sẽ yêu cầu hành vi đó. Đây là điều tốt nhất tôi có thể đưa ra ...

CẢNH BÁO: Mã này nguy hiểm. Xin hãy thương xót tôi vì đã gửi một sự ghê tởm như vậy. Nó chỉ là bằng chứng về khái niệm.

public class Lowest<K> implements Comparable<K> { 
    public int compareTo(K other) { 
     return -1; 
    } 
} 

Và sau đó ...

public class Test { 
    public <K extends Comparable<K>> K findMaximum(List<K> values) throws Exception { 
     K lowest = (K) new Lowest<K>(); /// XXX DANGER! Losing compile-time safety!!! 

     K maximum = lowest; 
     for (K value : values) { 
      if (maximum.compareTo(value) < 0) { 
       maximum = value; 
      } 
     } 

     if (maximum == lowest) { 
      throw new Exception("Could not find a maximum value"); 
     } else { 
      return maximum; 
     } 
    } 
} 
+0

Ok, điều này hoàn toàn kỳ lạ. Chúng tôi đã đưa ra nhận xét giống nhau về câu hỏi trong vòng một giây, và sau đó chúng tôi đợi 20 phút và đăng gần như cùng một mã trong vòng 15 giây của nhau. Tôi nghĩ tôi cần nghỉ ngơi một chút ... –

+0

@mmyers: Lạ thật! Tôi nghĩ tôi sẽ nghỉ một thời gian dài. :) –

+1

Tôi không chắc điều gì tồi tệ hơn, mặc dù: sử dụng sự phản chiếu của tôi để tìm một người xây dựng (cho một lớp không có tầm thường), hoặc dàn diễn viên của bạn không phải là K đến K. –

1

xem xét không làm K một chung, nhưng sử dụng một giao diện mà kết thúc tốt đẹp các wrapper nguyên thủy (một wrapper đôi!).

import java.util.HashMap; 


public class NodeWrapper<K extends Comparable<K>> implements Comparable<NodeWrapper<K>> { 

    private static HashMap<Class, NodeWrapper> minVals = new HashMap<Class, NodeWrapper>(); 

    private K value; 

    private NodeWrapper() { 
     super(); 
    } 

    public NodeWrapper(K value, Class<K> clazz) { 
     super(); 
     this.value = value; 

     if (minVals.get(clazz)==null) { 
      minVals.put(clazz, new NodeWrapper<K>()); 
     } 
    } 

    public K getValue() { 
     return value; 
    } 

    public static NodeWrapper getMinValue(Class clazz){ 
     return minVals.get(clazz); 
    } 

    public void setValue(K value) { 
     this.value = value; 
    } 

    @Override 
    public int compareTo(NodeWrapper<K> o) { 
     NodeWrapper min = minVals.get(this.getClass()); 
     if (this==min && o==min) { 
      return 0; 
     } else if (this==min){ 
      return -1; 
     } else if (o==min){ 
      return 1; 
     } else { 
      return this.value.compareTo(o.value); 
     } 
    } 

} 

Tóm lại, ý tưởng là bất cứ khi nào một lớp mới được khởi tạo, giá trị tối thiểu được tạo và đưa vào băm tĩnh lưu trữ giá trị tối thiểu cho mỗi lớp. (Thực tế, những giá trị này KHÔNG có gì cả, chỉ là một đối tượng sentinel, nhưng vì chúng ta sẽ sử dụng đối tượng bình đẳng để xác định xem cái gì là giá trị min, điều này không có vấn đề gì cả.) Tất cả những gì cần thiết là đối tượng được so sánh có thể so sánh được cho các trường hợp khác của chính nó nói chung.

Một nhược điểm là khi bạn gọi getMinValue bạn sẽ có cảnh báo trình biên dịch vì loại trả về sẽ không có thông tin chung. Có thể có một cách thanh lịch hơn xung quanh điều này, nhưng tôi không thể nghĩ về nó ngay bây giờ.

Ý tưởng chung này có thể khá tốt đẹp. Tuy nhiên, tôi nên thực sự căng thẳng: điều này sẽ hoàn toàn phá vỡ nếu bạn thử nó với bất kỳ đa hình hoặc bất kỳ pha trộn của các lớp học cùng có thể so sánh. Long s và Integer s trong cùng một cây sẽ phá hủy hoàn toàn bạn.

2

er ... vấn đề lại là gì?

PriorityQueue, giống như tất cả Collections, cho phép bạn sử dụng phiên bản của đối tượng remove đối tượng đó từ bộ sưu tập.

+0

Haha. Tập trung :-) – KarlP

+0

Cũng nói. Tôi khuyên rằng xhaker kiểm tra mã nguồn cho lớp PriorityQueue cho một ví dụ. –

2

Bạn có thể tạo lớp bao bọc để "thêm" giá trị tối thiểu và tối đa cho tất cả các loại. Nó chỉ có hai trường hợp tĩnh đại diện cho tối thiểu và tối đa, và sau đó các trường hợp khác quấn một số giá trị khác của một số loại. Khi chúng tôi so sánh, chúng tôi kiểm tra xem một trong những điều đó là tối thiểu hay tối đa và trả lại kết quả phù hợp; và nếu không, chúng tôi chỉ thực hiện so sánh tương tự như loại cơ bản. Một cái gì đó như thế này:

class Extended<T extends Comparable<? super T>> implements Comparable<Extended<T>> { 
    private Extended() { } 

    private static Extended min = new Extended(); 
    private static Extended max = new Extended(); 

    @SuppressWarnings("unchecked") 
    public static <T extends Comparable<? super T>> Extended<T> getMin() { 
     return (Extended<T>)min; 
    } 
    @SuppressWarnings("unchecked") 
    public static <T extends Comparable<? super T>> Extended<T> getMax() { 
     return (Extended<T>)max; 
    } 

    public T value; 

    public Extended(T x) { value = x; } 

    public int compareTo(Extended<T> other) { 
     if (this == other) return 0; 
     else if (this == min || other == max) return -1; 
     else if (this == max || other == min) return 1; 
     else return this.value.compareTo(other.value); 
    } 
}