2016-11-04 3 views
0

SimpleArrayMapArrayMapのクラスは、HashMapの方がより効率的(少数品目)の置換であることを意味しています。 HashMapは予測可能な反復順序(LinkedHashMapとは異なります)を持っていませんが、SimpleArrayMapArrayMapクラス内のいくつかの方法が気付いています。 keyAt(int index)valueAt(int index)removeAt(int index)などのSimpleArrayMapとArrayMapは注文を保持するためのものですか?

方法はSimpleArrayMapArrayMapは予測可能な方法でその項目を格納ことを示しているように見えます。また、これらの方法は、それらの項目にアクセスすることが非常に便利になるだろうので、私は、各ページのタイトルとフラグメントを保持するためにFragmentPagerAdapterArrayMapを追加しました:

public class TabPagerAdapter extends FragmentPagerAdapter { 

    private final ArrayMap<CharSequence, Fragment> mData = new ArrayMap(); 

    public TabPagerAdapter(FragmentManager manager) { 
     super(manager); 
    } 

    public void addPage(CharSequence title, Fragment fragment) { 
     mData.put(title, fragment); 
    } 

    @Override 
    public CharSequence getPageTitle(int position) { 
     return mData.keyAt(position); 
    } 

    @Override 
    public Fragment getItem(int position) { 
     return mData.valueAt(position); 
    } 

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

} 

私はアイテムがgetPageTitle()によって返されたことを実際に気づいたもののおよびgetItem()は必ずしも私がArrayMapに追加した順番ではありません。しかし、これらのクラスのインデックスが予測不可能な場合(なぜMap#get(Object key)メソッドを使用するのではなく)、インデックスでキーと値を返すメソッドを持つのはなぜですか?

SimpleArrayMapArrayMapは注文を保留するものですか?私は何か間違っているのですか?あるいは、もしそうでなければ、なぜ彼らは前述の方法を含んでいますか?

答えて

1

SimpleArrayMapの実装を見ると、put、putAll、またはremoveの各メソッドが呼び出されると、動的に拡大縮小するように見えます。その時点でインデックスが変わることがあります。電話をかけた後にnotifyDataSetChanged()に電話すると、より良い時間を過ごすことができます。今はこれがあなたのコードについて推論するだけなので、保証はありません。 :)

indexOfメソッドは、マップを縮小するときにインデックスへのキーハッシュの内部配列が更新されていないように見えるため、アイテムの想定インデックスを検索する必要があります。インデックスは明らかに変わる可能性があります。

int index = ContainerHelpers.binarySearch(mHashes, N, hash); 

// If the hash code wasn't found, then we have no entry for this key. 
if (index < 0) { 
    return index; 
} 

// If the key at the returned index matches, that's what we want. 
if (key.equals(mArray[index<<1])) { 
    return index; 
} 

// Search for a matching key after the index. 
int end; 
for (end = index + 1; end < N && mHashes[end] == hash; end++) { 
    if (key.equals(mArray[end << 1])) return end; 
} 

// Search for a matching key before the index. 
for (int i = index - 1; i >= 0 && mHashes[i] == hash; i--) { 
    if (key.equals(mArray[i << 1])) return i; 
} 

// Key not found -- return negative value indicating where a 
// new entry for this key should go. We use the end of the 
// hash chain to reduce the number of array entries that will 
// need to be copied when inserting. 
return ~end; 

インデックスされたメソッドは、マップの変更が行われていないことがわかっている用途で使用されている可能性があります。

UPDATE: これは、あなたがそれをやりたいようにするために、あなたはあなたの位置はあなたに安定したアイテムIDを与えないため、同様 public long getItemId(int position)を実装する必要があります。

基本マップの変更が必要な場合は、キャッシュされたインデックスを更新する必要があるため、index-methodsの使用はおそらく最良の選択ではないと言います。

+0

'put()'を呼び出した後に 'notifyDataSetChanged()'を呼び出すことはスマートになります。これまでのところ、私は 'ViewPager'でアダプタを設定する前にアイテムを追加しただけなので、現在のコードには違いはありません。 – Bryan

+0

あなたの推論では、これは非常に直感的ではないようです。それらのキーが挿入順序から変更できる場合、各挿入後にすべてのキーに対して 'indexOfKey() 'を呼び出すだけで、どのキーが各キーと値のペアに属するかを知る唯一の方法になります。これは、すべてのインデックスを完全に無用にして、本質的に 'indexOfKey()'を値にアクセスする中途半端にしているようです。そのような中間者がいなくても、 'get(Object key)'メソッドはそうすることができます。 – Bryan

+0

さて、はい。マップを変更する場合は、索引のリストを再構築する必要があります。私が言っていることは、基本的な配列が順序を保持することは保証されていないということです。しかし、オブジェクトが特定のインデックスに存在し、マップが変更されていないことが既に分かっている場合は、そのインデックスを使用できます。 –

関連する問題