1

save() と rollback() を標準のマップに追加するための高速で便利な方法を探しています。クラス Table のオブジェクト 'table' があり、これが 'rows' というプライベート マップを持っているとしましょう。私が達成しようとしているのは、Row が次のようなことを行うための高速でメモリを浪費しない方法です。

row = new Row();
table.addRow(row).setValue("col1", "foo").setValue("col2", "bar").save();
row.setValue("col2", "beer");
System.out.println(table.getRows()); // 1. col1=foo, col2=bar

row.save();
System.out.println(table.getRows()); // 1. col1=foo, col2=beer

実際、私の設計は非常に簡単です。addRow() が呼び出されると、マップ内の行を put() します。バッファーも一時要素もありません。Row インスタンス全体を行コレクションに渡すだけです。しかし、高速な方法と (可能であれば) 行の重複を避ける必要があります。

何か案が?

4

3 に答える 3

3

これは、「新しい値と古い値をメモリに入れたいが、新しい値と古い値をメモリに入れたくない」のように聞こえます。

オプション:

addeda)保存するときのすべての要素のマップputAll

b)の代わりに<ClassKey, ClassValue>、マップはを保持します<ClassKey, ClassValue2>。新しいインスタンスと古いインスタンスのValue22つのアイテムを保持します。ClassValuesave、新しいもの(ある場合)を古いものに渡します。これは、各「トランザクション」のほとんどのエントリを変更する場合にのみ役立ちます。

言及されていないのは、要素を削除する問題です。これにより、さらに多くの喜びがもたらされます。オプション2を使用すると、ブール値をValue2に設定できます。オプションaを使用すると、より多くの回避策が必要になります。

于 2012-12-17T22:02:02.077 に答える
2

私が達成しようとしているのは、Row が次のようなことを行うための高速でメモリを浪費しない方法です。

途中で失敗した場合に備えて、どこかに「ロールバック」を保持する必要があるため、メモリを浪費します。これが、データベースがこれらの種類のものを処理する方法です。

必要な機能を取得するには、独自のカスタム トランザクション ロジックを実装する必要があります。これにより、マップへの変更を正しくロールバック/保持できます。このトランザクション内で、トランザクション中に発生したすべてを追跡する必要があります。これは、トランザクションの処理中に元のマップに一時的な書き込みを行うためです。その後、永続化/更新の失敗から回復する必要があります。

行の重複を避けるために、HashMap はすでにその問題からあなたを救います。2 つのオブジェクトが同じコードを生成した場合に正しくレポートするハッシュ関数を正しく実装していると仮定すると、ハッシュに関して「潜在的に」等しいとは言えません。

于 2012-12-17T21:56:55.527 に答える
0
  • カスタム Map クラス内に 2 つのマップ フィールドを保持 originalMapし、temporaryMap.
  • 読み取り操作は に委任されoriginalMap、書き込み操作は に委任されtemporaryMapます。
  • rollback()への浅いコピーoriginalMaptemporaryMapおよびcommit()その逆。キーと値は複製されないため、参照のみが保持され、メモリは「無駄」になりません。

package com.example;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import lombok.NonNull;
import lombok.ToString;

@ToString
public class TransactionalMap<K, V> implements Map<K, V> {
  
  private Map<K, V> originalMap;
  private Map<K, V> temporaryMap;
  
  public TransactionalMap() {
    this(new HashMap<>());
  }
  
  public TransactionalMap(@NonNull Map<K, V> impl) {
    if (impl instanceof TransactionalMap) {
      throw new IllegalArgumentException("Must provide valid implementation instance");
    }
    this.originalMap = new HashMap<>(impl);
    this.temporaryMap = new HashMap<>(originalMap);
  }

  @Override
  public int size() {
    return originalMap.size();
  }

  @Override
  public boolean isEmpty() {
    return originalMap.isEmpty();
  }

  @Override
  public boolean containsKey(Object key) {
    return originalMap.containsKey(key);
  }

  @Override
  public boolean containsValue(Object value) {
    return originalMap.containsValue(value);
  }

  @Override
  public V get(Object key) {
    return originalMap.get(key);
  }

  @Override
  public V put(K key, V value) {
    return temporaryMap.put(key, value);
  }

  @Override
  public V remove(Object key) {
    return temporaryMap.remove(key);
  }

  @Override
  public void putAll(Map<? extends K, ? extends V> m) {
    temporaryMap.putAll(m);
  }

  @Override
  public void clear() {
    temporaryMap.clear();
  }

  @Override
  public Set<K> keySet() {
    return originalMap.keySet();
  }

  @Override
  public Collection<V> values() {
    return originalMap.values();
  }

  @Override
  public Set<Entry<K, V>> entrySet() {
    return originalMap.entrySet();
  }
  
  private void sync(Map<K, V> src, Map<K, V> tgt) {
    tgt.putAll(src);
    tgt.forEach((k, v) -> {
      if (!src.containsKey(k)) tgt.remove(k);
    });
  }
  
  public void commit() {
    sync(temporaryMap, originalMap);
  }
  
  public void rollback() {
    sync(originalMap, temporaryMap);
  }

}

ロンボクを使用してボイラープレート コードを生成する

于 2021-12-31T05:00:37.767 に答える