2009-05-24 36 views
6

Tôi có một danh sách các tệp. Tôi muốn quét qua và giữ số lượng tệp có cùng kích thước. vấn đề là với các filesize dài, như chúng ta biết, hashmap sẽ chỉ nhận một đối tượng chứ không phải là một nguyên thủy. Vì vậy, sử dụng new Long(filesize), tôi đặt nó vào hashmap. thay vì nhận được một cặp (filesize, count), tôi có một danh sách (filesize, 1) do thực tế là mỗi obj Long là duy nhất.Giữ một cặp nguyên thủy trong một Java HashMap

Tôi làm cách nào để xây dựng bộ tích lũy này?

bất kỳ giải pháp nào cho 1.4.2?

Trả lời

15

Bạn chỉ cần làm theo cách này:

Map<Long, Integer> count = new HashMap<Long, Integer>(); 
for (File file : files) { 
    long size = file.getTotalSpace(); 
    Integer n = count.get(size); 
    if (n == null) { 
    count.put(size, 1); 
    } else { 
    count.put(size, n + 1); 
    } 
} 

Có một số auto-boxing và unboxing xảy ra ở đây.

3

hoặc bạn có thể sử dụng AtomicInteger làm số nguyên có thể thay đổi.

Map<Long, AtomicInteger> count = new HashMap<Long, AtomicInteger>(); 
for (File file : files) { 
    long size = file.length(); // getTotalSpace() get the space consumed (e.g. a multiple of 8K) rather the actual file size. 
    AtomicInteger n = count.get(size); 
    if (n == null) { 
    count.put(size, new AtomicInteger(1)); 
    } else { 
    n.getAndIncrement(); 
    } 
} 
7

Thay vì sử dụng new Long(size), bạn nên sử dụng Long.valueOf(size). sẽ trả về cùng một tham chiếu dài được lưu trong bộ nhớ cache, và cũng nên tăng hiệu suất (không phải là nó sẽ hiển thị trừ khi bạn thực hiện hàng triệu hoạt động new Long()).

ps. chỉ hoạt động đối với java 1.5 hoặc cao hơn

+0

AFAICT trong 1,6 Long.valueOf chỉ lưu trữ 256 chờ đợi mà dang chân không . Bất kỳ thứ gì có giá trị cao hơn 128 sẽ không được lưu trữ, các giá trị tương tự dưới -127. –

+0

cho 1,6 (không phải 1,5 hoặc dưới afaik), bạn có thể thay đổi hành vi đó bằng cách đặt -XX: AutoBoxCacheMax = 1000 (xem http://www.javaspecialists.eu/archive/Issue191.html) - tho nếu ứng dụng của bạn bị chậm lại bởi hoạt động như vậy đã có, sau đó tôi nghi ngờ theres một số vấn đề thuật toán ở đó ... – Chii

1

Mở rộng những gì cletus đã viết.

Giải pháp của anh ấy tốt, ngoại trừ nó chỉ lưu trữ từng tệp mà bạn gặp phải và số lượng tệp có kích thước này. Nếu bạn muốn biết những tập tin nào là cấu trúc dữ liệu này sẽ vô ích đối với bạn vì vậy tôi không nghĩ rằng giải pháp cletus là hoàn toàn. Thay vào đó tôi sẽ làm

Map<Long, Collection<File>> count = new HashMap<Long, Collection<File>>(); 
for (File file : files) { 
long size = file.getTotalSpace(); 
Collection<File> c = count.get(size); 
if (c == null) { 
    c = new ArrayList<File>(); //or whatever collection you feel comfortable with 
    count.put(size, c); 
} 
    c.add(file); 
} 

sau đó bạn có thể nhận được số lượng các tập tin với c.size() và bạn có thể lặp qua tất cả các tập tin với con số đó một cách dễ dàng mà không cần phải chạy thủ tục này một lần nữa.

+1

Bạn quên đặt arraylist vào bản đồ. –

+0

cảm ơn! haha, tôi có xu hướng quên những điều này và họ trở lại để cắn tôi vào mông. – ldog

+0

giải pháp hữu ích, mặc dù giải pháp cletus là gần gũi hơn với những gì tôi cần. – zeroin23

1

Tôi nghĩ rằng có nhiều điều này và chúng tôi sẽ cần thêm chi tiết từ bạn. Tôi giả sử bạn biết chắc chắn có nhiều hơn một tệp có kích thước nhất định, nếu không trước tiên tôi sẽ kiểm tra xem đó là trường hợp. Đối với tất cả những gì bạn biết, bạn chỉ cần có rất nhiều tệp với kích thước tệp duy nhất.

Bạn nói:

... do thực tế rằng mỗi obj Long là độc đáo.

Tôi không nghĩ đây là vấn đề. Trong khi điều này có thể đúng tùy thuộc vào cách bạn đang instantiating Longs, nó không nên ngăn chặn HashMaps từ hành xử theo cách bạn muốn. Miễn là hai đối tượng chính trả về cùng một giá trị hashCode() và phương thức equals() nói rằng chúng bằng nhau, HashMap của bạn sẽ không tạo ra một mục nhập khác cho nó. Trong thực tế, bạn không thể thấy "danh sách (filesize, 1)" với cùng giá trị kích cỡ (trừ khi bạn viết Long và không thực hiện hashCode()/equals() một cách chính xác).

Điều đó nói rằng, mã của Cletus sẽ hoạt động nếu bạn đang sử dụng Java 5 trở lên, nếu bạn đang sử dụng Java 1.4 trở xuống, bạn sẽ cần phải thực hiện thủ công/unboxing của riêng mình hoặc xem Apache Commons Collections .Dưới đây là phiên bản pre-Java 5 ví dụ Cletus':

Map count = new HashMap(); 
for (Iterator filesIter = files.iterator(); filesIter.hasNext();) { 
    File file = (File)filesIter.next(); 
    long size = file.getTotalSpace(); 
    Integer n = count.get(size); 
    if (n == null) { 
    count.put(size, Integer.valueOf(1)); 
    } else { 
    count.put(size, Integer.valueOf(n.intValue() + 1)); 
    } 
} 
+0

nó đã xảy ra trên một máy jdk1.4.2 ... – zeroin23

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