剖析.NET Framework源码—数据结构List<T> (三)
(8)FindIndex : 三个重载。搜索与指定谓词所定义的条件相匹配的元素,并返回 List<T>或它一部分中第一个匹配的元素从0开始的索引
public int FindIndex(int startIndex, int count, Predicate<T> match)
{
if ((uint)startIndex > (uint)_size)
{
throw new ArgumentOutOfRangeException();
}
if (count < 0 || startIndex > _size - count)
{
throw new ArgumentOutOfRangeException();
}
if (match == null)
{
throw new ArgumentNullException();
}
int endIndex = startIndex + count;
for (int i = startIndex; i < endIndex; i++)
{
if (match(_items[i]))
return i;
}
//如果遍历完成后仍找不到相匹配的元素,则返回 -1
return -1;
}
public int FindIndex(Predicate<T> match)
{
return FindIndex(0, _size, match);
}
public int FindIndex(int startIndex, Predicate<T> match)
{
return FindIndex(startIndex, _size - startIndex, match);
}
(9)FindAll : 搜索与指定谓词所定义的条件相匹配的所有元素
public List<T> FindAll(Predicate<T> match)
{
if (match == null)
{
throw new ArgumentNullException();
}
//用于存储满足匹配条件的所有元素
List<T> list = new List<T>();
for (int i = 0; i < _size; i++)
{
if (match(_items[i]))
{
list.Add(_items[i]);
}
}
return list;
}
(10)FindLastIndex : 三个重载。搜索与指定谓词定义的条件相匹配的元素,并 返回List<T>或它一部分中最后一个匹配元素从0开始的索引
public int FindLastIndex(int startIndex, int count, Predicate<T> match)
{
if (match == null)
{
throw new ArgumentNullException();
}
if (_size == 0)
{
if (startIndex != -1)
{
throw new ArgumentOutOfRangeException();
}
}
else
{
if ((uint)startIndex >= (uint)_size)
{
throw new ArgumentOutOfRangeException();
}
}
if (count < 0 || startIndex - count + 1 < 0)
{
throw new ArgumentOutOfRangeException();
}
int endIndex = startIndex - count;
//从后往前搜索count个
for (int i = startIndex; i > endIndex; i--)
{
if (match(_items[i]))
{
return i;
}
}
return -1;
}
这个方法比较长,首先进行了很多的参数合法性验证,要注意startIndex - count + 1 = 0 这个临界条件。表示从startIndex向前搜索count个元素,若count等于startIndex+1,表示需要搜索startIndex之前(包括startIndex)的所有元素(至索引为0)!
该方法其他的重载形式为:
public int FindLastIndex(Predicate<T> match)
{
//从最后一个元素向前搜索至第一个元素(索引位置为0)
return FindLastIndex(_size - 1, _size, match);
}
public int FindLastIndex(int startIndex, Predicate<T> match)
{
//从startIndex处(包括startIndex)向前搜索到第一个元素
return FindLastIndex(startIndex, startIndex + 1, match);
}
(11)T FindLast(Predicate<T> match)
public T FindLast(Predicate<T> match)
{
if (match == null)
{
throw new ArgumentNullException();
}
//从最后一个元素开始向前遍历
for (int i = _size - 1; i >= 0; i--)
{
if (match(_items[i]))
{
return _items[i];
}
}
//若搜索完毕后没有找到匹配元素,则返回泛型T的默认值
return default(T);
}
与该方法类似,List中实现了一个Find方法,该方法同样搜索与指定谓词中定义的条件相匹配的元素,并返回整个List<T>中第一个匹配元素
public T Find(Predicate<T> match)
{
if (match == null)
{
throw new ArgumentNullException();
}
//从第一个元素向后遍历
for (int i = 0; i < _size; i++)
{
if (match(_items[i]))
{
return _items[i];
}
}
return default(T);
}
(12)Exists:确定List<T>是否包含与指定谓词所定义的条件相匹配的元素
public bool Exists(Predicate<T> match)
{
return FindIndex(match) != -1;
}
(13)IndexOf :3个重载。返回 List或它的一部分中某个值的第一个匹配项的从 零开始的索引
//从index开始搜索count个元素
public int IndexOf(T item, int index, int count)
{
if (index > _size)
throw new ArgumentOutOfRangeException();
if (count < 0 || index > _size - count)
throw new ArgumentOutOfRangeException();
return Array.IndexOf(_items, item, index, count);
}
//从第一个元素开始搜索到最后一个元素
public int IndexOf(T item)
{
return Array.IndexOf(_items, item, 0, _size);
}
int System.Collections.IList.IndexOf(Object item)
{
if (IsCompatibleObject(item))
{
return IndexOf((T)item);
}
return -1;
}
//从index开始搜索到最后一个元素
public int IndexOf(T item, int index)
{
if (index > _size)
throw new ArgumentOutOfRangeException();
return Array.IndexOf(_items, item, index, _size - index);
}
与此方法类似的还有LastIndexOf的三种重载形式。返回 List或它的一部分中某个值的最后一个匹配项的从零开始的索引。
(14)RemoveAt:移除List指定索引处的元素
public void RemoveAt(int index)
{
if ((uint)index >= (uint)_size)
{
throw new ArgumentOutOfRangeException();
}
_size--;
if (index < _size)
{
//将index处后面的所有元素依次向前移一位
Array.Copy(_items, index + 1, _items, index, _size - index);
}
//最后一个多余的位置设置为泛型T的默认值
_items[_size] = default(T);
_version++;
}
(15) Remove : 从List中移除特定对象的第一个匹配项
public bool Remove(T item)
{
//首先找到该元素的第一个匹配项的索引
int index = IndexOf(item);
if (index >= 0)
{
//移除List指定索引处的元素
RemoveAt(index);
return true;
}
return false;
}
(16)RemoveAll:移除与指定的谓词所定义的条件相匹配的所有元素
这个方法是很有技巧的一个方法!
public int RemoveAll(Predicate<T> match)
{
if (match == null)
{
throw new ArgumentNullException();
}
int freeIndex = 0;
//freeIndex指定第一个需要被移除的元素的索引位置
while (freeIndex < _size && !match(_items[freeIndex]))
freeIndex++;
//遍历完成后返回0,没有移除任何一个元素
if (freeIndex >= _size)
return 0;
int current = freeIndex + 1;
while (current < _size)
{
// Find the first item which needs to be kept.
while (current < _size && match(_items[current]))
current++;
if (current < _size)
{
_items[freeIndex++] = _items[current++];
}
}
Array.Clear(_items, freeIndex, _size - freeIndex);
//已经移除的元素的个数
int result = _size - freeIndex;
_size = freeIndex;
_version++;
return result;
}
浙公网安备 33010602011771号