6

ファイルのリストがあります。スキャンして、同じサイズのファイルの数を数えたいと思います。問題は、ファイルサイズが長いことです。ご存知のように、ハッシュマップはプリミティブではなくオブジェクトのみを取り込みます。を使用new Long(filesize)して、ハッシュマップに入れました。(filesize, count) のペアを取得する代わりに、(filesize, 1) のリストを取得しました。これは、各 Long obj が一意であるためです。

このアキュムレータを構築するにはどうすればよいですか?

1.4.2 の解決策はありますか?

4

6 に答える 6

15

次のようにするだけです。

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);
  }
}

ここでは、オートボクシングとアンボクシングが行われています。

于 2009-05-24T05:03:52.147 に答える
6

を使用する代わりに、 を使用new Long(size)する必要がありますLong.valueOf(size)。これは、内部にキャッシュされているのと同じ Long 参照を返し、パフォーマンスも向上させるはずです (これらの操作を何百万回も実行しない限り、表示されるわけではありませんnew Long())。

ps。Java 1.5 以降でのみ動作します

于 2009-05-24T09:02:23.690 に答える
4

Troveを使用してペア (long,int) を格納できます - TLongIntHashMap

于 2009-05-25T00:30:34.010 に答える
3

または、AtomicInteger を変更可能な整数として使用できます。

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();
  }
}
于 2009-05-24T08:59:20.297 に答える
1

これには他にもあると思います。あなたからの詳細が必要になります。特定のサイズのファイルが確実に複数あることを知っていると仮定しています。ご存じのとおり、一意のファイル サイズを持つファイルがたくさんあるだけです。

あなたが言及した:

...各 Long obj が一意であるためです。

これは問題ではないと思います。Long をインスタンス化する方法によっては、これが当てはまる場合もありますが、HashMap が希望どおりに動作するのを妨げるべきではありません。2 つのキー オブジェクトが同じ hashCode() 値を返し、equals() メソッドがそれらが等しいと言う限り、HashMap は別のエントリを作成しません。実際、同じファイルサイズ値を持つ「(filesize, 1) のリスト」を表示することはできないはずです (独自の Long を記述し、hashCode()/equals() を正しく実装できなかった場合を除く)。

とはいえ、Java 5 以降を使用している場合は Cletus のコードが機能するはずです。Java 1.4 以下を使用している場合は、手動でボックス化/ボックス化解除を行うか、Apache Commons Collectionsを調べる必要があります。Cletus の例の Java 5 以前のバージョンは次のとおりです。

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));
  }
}
于 2009-05-24T10:11:21.557 に答える
1

cletus が書いたものを拡張します。

彼のソリューションは問題ありませんが、遭遇した各ファイルサイズとそのサイズのファイル数のみを保存します。それらがどのファイルであるかを知りたい場合、このデータ構造は役に立たないため、cletus ソリューションは完全ではないと思います。代わりに私はするだろう

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);
} 

次に、 c.size() でファイルの数を取得でき、この手順を再度実行することなく、その数のすべてのファイルを簡単に反復処理できます。

于 2009-05-24T09:08:13.930 に答える