2013-03-21 43 views
5

Tôi cần bản đồ trong đó khóa của tôi phải dựa trên 3 cột, giả sử C1, C2, C3. C1 có mức độ ưu tiên cao nhất. C2 có một ít hơn C1C3 có một ít hơn C2.Bản đồ Java có các phím của 3 cột

Làm cách nào để tạo khóa trong bản đồ sao cho nếu ai đó yêu cầu thông tin trên C1, tôi có thể cung cấp tất cả các giá trị có C1. Tôi cũng có thể trả lại tất cả các giá trị nếu được yêu cầu C1 & C2

+4

Bạn có thể chỉ cho chúng tôi một số trường hợp kiểm tra không? Đầu vào của bạn là gì và đầu ra của bạn? –

+2

Câu hỏi không rõ ràng .... – AmitG

+0

Đây không phải là vấn đề tiêu chuẩn. Cho phép tiếp cận vấn đề này cụ thể cho kịch bản hiện tại cho việc sử dụng của bạn. Bạn có thể vui lòng cho biết loại dữ liệu của C1, C2 và C3 là gì? Nếu chúng là số nguyên thì đó sẽ là phạm vi của chúng? – Saurabh

Trả lời

2

Bạn có thể sử dụng chiến lược tương tự như chỉ số multicolumn trong cơ sở dữ liệu, nếu cột quan trọng của bạn có thể được đặt hàng (ví dụ, trong Java, họ cần phải là Comparable) và có thể dễ dàng xác định giá trị tối đa và tối thiểu cho tất cả trừ giá trị đầu tiên.

Một ví dụ với các cột số nguyên:

public class Key implements Comparable<Key> { 
    int c1, c2, c3; 

    private static final int c2_min = Integer.MIN_VALUE; 
    private static final int c2_max = Integer.MAX_VALUE; 
    private static final int c3_min = Integer.MIN_VALUE; 
    private static final int c3_max = Integer.MAX_VALUE; 

    @Override 
    public int compareTo(Key o) { 
     if (c1!=o.c1) return Integer.compare(c1, o.c1); 
     if (c2!=o.c2) return Integer.compare(c2, o.c2); 
     return Integer.compare(c3, o.c3); 
    } 

    // constructor, equals, ... 

} 

và sau đó bạn có thể nhận được tất cả các mục cho một số giá trị k1 trong c1 như thế này:

map.subMap(new Key(k1, Key.c2_min, 0), new Key(k1, Key.c2_max, 0)); 

Tương tự như vậy, sử dụng hai cột đầu tiên:

map.subMap(new Key(k1, k2, Key.c3_min), new Key(k1, k2, Key.c3_max)); 
+0

Cảm ơn, tôi có câu hỏi loại của tôi là byte []. Làm thế nào để xác định giá trị MAX và MIN – Avinash

+0

Giả sử một [so sánh byte] (http://stackoverflow.com/questions/5108091/java-comparator-for-byte-array-lexicographic), bạn có thể sử dụng 'MIN = byte mới [ 0] '. Đối với 'MAX', nếu bạn có kích thước mảng tối đa, chỉ cần sử dụng nó và khởi tạo tất cả các phần tử bằng' Byte.MAX_VALUE'. Nếu không, bạn phải chọn một số cá thể (được định nghĩa là 'static final') và kiểm tra rõ ràng nó trong' compareTo' với '=='. Cuối cùng, tùy thuộc vào ứng dụng của bạn, 'null' cũng có thể hoạt động như một giá trị tối đa bằng cách xem xét nó một cách rõ ràng trong' compareTo'. – jop

0

Bằng "ưu tiên", tôi đoán bạn có nghĩa là những gì thường được gọi là khóa chính, phụ và đại học.

Nếu chúng là tất cả các trường chuỗi, hãy ghép chúng vào một chuỗi đơn và sử dụng nó làm khóa. Trong trường hợp của bạn, khóa là C1 + C2 + C3 (trong đó "+" tham chiếu đến chuỗi nối).

+0

nhưng sau đó làm cách nào bạn sẽ tìm nạp giá trị chỉ tương ứng với C1 hoặc chỉ C1 và C2? – Saurabh

2

Sử dụng ba bản đồ.

One Map<C1, V> and one Map<C2, V> and one Map<C3, V>. 

Bạn có thể bọc ba bản đồ vào một lớp và triển khai phương pháp của bạn.

0

Bản đồ sẽ luôn trả lại chỉ một giá trị cho khóa. Bạn không thể trả lại nhiều giá trị dựa trên nội dung lớp chính của bạn.

Cách đơn giản là giữ một bản đồ riêng biệt cho mỗi loại khóa và trả lại kết quả phù hợp dựa trên khóa đã truyền.

0

Chỉ mục ba cấp nơi có thể sử dụng khóa cấp cao hơn để truy cập tất cả các khóa và đối tượng cấp thấp hơn sẽ yêu cầu bản đồ ba cấp.

class ThreeLevelMap<K1,K2,K3,V> 
{ 
    private Map<K1,Map<K2,Map<K3,V>>> store = new HashMap<K,Map<K2,Map<K3,V>>>(); 
    ... 
    public V put(K1 key1, K2 key2, K3 key3, V value) { ... } 
    public V get(K1 key1, K2 key2, K3 key3) { ... } 

    public static class TLMEntry<K1,K2,K3,V> 
    { 
    ... 
    } 
    public Collection<TLMEntry<K1,K2,K3,V>> get(K1 key1, K2 key2) { ... } 
    public Collection<TLMEntry<K1,K2,K3,V>> get(K1 key1) { ... } 
} 

Đây là bộ xương cơ bản nhưng sẽ giúp bạn đi đúng hướng.

0

Điều này có vẻ giống một vấn đề về cơ sở dữ liệu. Nếu bạn có cơ sở dữ liệu có bảng được cấu trúc như:

CREATE TABLE MyMap (
    id IDENTITY PRIMARY KEY, 
    c1 int, -- Change data types as needed. 
    c2 int, 
    c3 int, 
    v int); 

thì bạn chỉ cần phát hành các câu lệnh SELECT chống lại nó. Bạn có thể muốn sử dụng bất kỳ cơ sở dữ liệu Java trong bộ nhớ nào.

Nếu bạn không muốn làm điều đó, bạn có thể làm tương đương hoàn toàn trong Java chức năng bằng cách viết một container lớp giá trị lớp:

class Cdata { 
    private int c1; 
    private int c2; 
    private int c3; 
    private int v; 
    // Constructors and getters elided. 
    public boolean match(int c1) { 
     return this.c1 == c1; 
    } 
    public boolean match(int c1, int c2) { 
     return match(c1) && this.c2 == c2; 
    } 
    public boolean match(int c1, int c2, int c3) { 
     return match(c1, c2) && this.c3 == c3; 
    } 
} 

Sau đó tạo một danh sách và sử dụng một thư viện lập trình chức năng với bộ lọc phương pháp. Hoặc, chờ đợi cho Java 8 lambdas. Sử dụng Map<Integer, Map<Integer, Map<Integer, Integer>>>> quá khó hiểu.

0

Bạn có thể sử dụng TreeMap để đạt được mục tiêu của bạn. Tôi giả định như sau: bản đồ ba cột của bạn để 3 tăng giá trị số nguyên tức là

C1 = 1, C2 = 2, C3 = 3

nơi C1 = 1 là ưu tiên cao nhất và C2 = 2 là tiếp theo trong dòng và như vậy.

Lưu ý: Khóa của bạn không cần phải luôn là Số nguyên, bạn có thể sử dụng bất kỳ loại nào nếu bạn cung cấp Comparator thích hợp cho TreeMap của mình.

Với điều này tại chỗ, bạn có thể làm một cái gì đó như:

TreeMap<Integer, String> treeMap = new TreeMap<Integer, String>(); 
treeMap.put(1, "One"); 
treeMap.put(2, "two"); 
treeMap.put(3, "three"); 

List<String> list = getMappedValues(treeMap, 1);// returns One, Two, Three 
//List<String> list = getMappedValues(treeMap, 2);// returns Two, Three 
//List<String> list = getMappedValues(treeMap, 3);// returns Three 
//List<String> list = getMappedValues(treeMap, 4);// returns null 
if(list != null){ 
    //do something with the list of values 
} 

private static List<String> getMappedValues(TreeMap<Integer, String> map, Integer key) { 
    Entry<Integer, String> e = map.ceilingEntry(key); 
    if(e == null){ 
     return null; 
    } 
    List<String> list = new ArrayList<String>(); 
    while(e != null){ 
     list.add(e.getValue()); 
     key = e.getKey(); 
     e = map.higherEntry(key); 
    } 
    return list; 
} 
0

private class C { 

    public C() { 
     Map <Object ,String> ObjectC =new HashMap<Object, String>(); 
    } 
} 

private class B { 

    public B() { 
     Map <Object ,C> ObjectB =new HashMap<Object, C>(); 
    } 
} 

private class A { 

    public A() { 
     Map <Object ,B> ObjectA =new HashMap<Object, B>(); 
    } 
} 

Vì vậy, đây có thể hứa với em một cấu trúc đẹp mà bạn không cần phải làm nhiều việc hơn nữa như Bạn có thể nhận được tất cả các nội dung của A

MapVar.ObjectA.get(C1); 

nếu cả hai C1, C2 được cung cấp Bạn có thể gọi

MapVar.ObjectA.get(C1).ObjectB.get(C2); 

nếu cả C1, C2, C3 được cung cấp Bạn có thể gọi

MapVar.ObjectA.get(C1).ObjectB.get(C2).ObjectC.get(C3);; 

Sau đó, bạn chỉ có thể lặp qua bản đồ và nhận giá trị.

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