1. TList.remove->TList.Delete->TList.Move  
  2.  
  3. // 根据传入的Item 删除对应位置的数据   
  4. function TList.Remove(Item: Pointer): Integer;  
  5.  
  6. // 删除数据,使用move用后边的数据代替前边的数据  
  7. procedure TList.Delete(Index: Integer);  
  8.  
  9. Remove 后边的数据会代替前面的数据  
  10.  
  11. Pack 同样也会清理前面的数据  
  12.  
  13. TList 源码分析  
  14. TPointerList = array[0..MaxListSize - 1] of Pointer;  
  15. TList 的本质就是个无类型指针的数组  
  16.  
  17. TList = class(TObject)  
  18. private  
  19.     FList: PPointerList;  
  20.     FCount: Integer;  
  21.     FCapacity: Integer;  
  22. protected  
  23.     function Get(Index: Integer): Pointer;  
  24.     procedure Grow; virtual;  
  25.     procedure Put(Index: Integer; Item: Pointer);  
  26.     procedure Notify(Ptr: Pointer; Action: TListNotification); virtual;  
  27.     procedure SetCapacity(NewCapacity: Integer);  
  28.     procedure SetCount(NewCount: Integer);  
  29. public  
  30.     destructor Destroy; override;  
  31.     function Add(Item: Pointer): Integer;  
  32.     procedure Clear; virtual;  
  33.     procedure Delete(Index: Integer);  
  34.     class procedure Error(const Msg: string; Data: Integer); overload; virtual;  
  35.     class procedure Error(Msg: PResStringRec; Data: Integer); overload;  
  36.     procedure Exchange(Index1, Index2: Integer);  
  37.     function Expand: TList;  
  38.     function Extract(Item: Pointer): Pointer;  
  39.     function First: Pointer;  
  40.     function IndexOf(Item: Pointer): Integer;  
  41.     procedure Insert(Index: Integer; Item: Pointer);  
  42.     function Last: Pointer;  
  43.     procedure Move(CurIndex, NewIndex: Integer);  
  44.     function Remove(Item: Pointer): Integer;  
  45.     procedure Pack;  
  46.     procedure Sort(Compare: TListSortCompare);  
  47.     procedure Assign(ListA: TList; AOperator: TListAssignOp = laCopy; ListB: TList = nil);  
  48.     property Capacity: Integer read FCapacity write SetCapacity;  
  49.     property Count: Integer read FCount write SetCount;  
  50.     property Items[Index: Integer]: Pointer read Get write Put; default;  
  51.     property List: PPointerList read FList;  
  52. end;  
  53.  
  54. // 根据在List的索引返回数组中数据,以无类型指针返回  
  55. function TList.Get(Index: Integer): Pointer;  
  56. begin  
  57. if (Index < 0) or (Index >= FCount) then  
  58.     Error(@SListIndexError, Index);  
  59. Result :FList^[Index];  
  60. end;  
  61.  
  62. // 扩大数组中的内存分配,FCapacity 默认是16,Delta 为16和4,估计主要是避免过多次数的内存分配而产生内存碎片,所以一次分配多点,如果list要加载的数据过多,应该把FCapacity 设置相对大   
  63. procedure TList.Grow;  
  64. var  
  65. Delta: Integer;  
  66. begin  
  67. if FCapacity > 64 then  
  68.     Delta :FCapacity div 4  
  69. else  
  70.     if FCapacity > 8 then  
  71.       Delta :16 
  72.     else  
  73.       Delta :4;  
  74. SetCapacity(FCapacity + Delta);  
  75. end;  
  76.  
  77. // 代替数组中的数据,删除原有的数据, 同时调用Notify函数,传递lnDeleted, lnAdded 参数  
  78. procedure TList.Put(Index: Integer; Item: Pointer);  
  79. var  
  80. Temp: Pointer;  
  81. begin  
  82. if (Index < 0) or (Index >= FCount) then  
  83.     Error(@SListIndexError, Index);  
  84. if Item <> FList^[Index] then  
  85. begin  
  86.     Temp :FList^[Index];  
  87.     FList^[Index] :Item;  
  88.     if Temp <> nil then  
  89.       Notify(Temp, lnDeleted);  
  90.     if Item <> nil then  
  91.       Notify(Item, lnAdded);  
  92. end;  
  93. end;  
  94.  
  95. // TList.Grow 或者TList.SetCount调用,主要为重新分配内存,ReallocMem分配连续的内存  
  96. procedure TList.SetCapacity(NewCapacity: Integer);  
  97. begin  
  98. if (NewCapacity < FCount) or (NewCapacity > MaxListSize) then  
  99.     Error(@SListCapacityError, NewCapacity);  
  100. if NewCapacity <> FCapacity then  
  101. begin  
  102.     ReallocMem(FList, NewCapacity * SizeOf(Pointer));  
  103.     FCapacity :NewCapacity;  
  104. end;  
  105. end;  
  106.  
  107. // 如果NewCount大于现在有的内存,则扩大内存,SetCapacity(NewCount), 同时将Fcount 到 NewCount 之间的数据清空  
  108. ( if NewCount > FCount then  
  109.     FillChar(FList^[FCount], (NewCount - FCount) * SizeOf(Pointer), 0) ), 小则将Fcount 到 NewCount 之间的数据删除  
  110. ( for I :FCount - 1 downto NewCount do  
  111.       Delete(I);)  
  112. 最后将数组中的数目设为 NewCount  
  113.  
  114. procedure TList.SetCount(NewCount: Integer);  
  115. var  
  116. I: Integer;  
  117. begin  
  118. if (NewCount < 0) or (NewCount > MaxListSize) then  
  119.     Error(@SListCountError, NewCount);  
  120. if NewCount > FCapacity then  
  121.     SetCapacity(NewCount);  
  122. if NewCount > FCount then  
  123.     FillChar(FList^[FCount], (NewCount - FCount) * SizeOf(Pointer), 0)  
  124. else  
  125.     for I :FCount - 1 downto NewCount do  
  126.       Delete(I);  
  127. FCount :NewCount;  
  128. end;  
  129.  
  130. // 调用clear  
  131. destructor TList.Destroy;  
  132. begin  
  133. Clear;  
  134. end;  
  135.  
  136. // 先判断是否需要扩大内存分配,然后将Item添加到LIST默尾  
  137. function TList.Add(Item: Pointer): Integer;  
  138. begin  
  139. Result :FCount;  
  140. if Result = FCapacity then  
  141.     Grow;  
  142. FList^[Result] :Item;  
  143. Inc(FCount);  
  144. if Item <> nil then  
  145.     Notify(Item, lnAdded);  
  146. end;  
  147.  
  148. // 清空,将数据清空,同时将内存释放  
  149. procedure TList.Clear;  
  150. begin  
  151. SetCount(0);  
  152. SetCapacity(0);  
  153. end;  
  154.  
  155. // 删除数据,使用move用后边的数据代替前边的数据  
  156. procedure TList.Delete(Index: Integer);  
  157. var  
  158. Temp: Pointer;  
  159. begin  
  160. if (Index < 0) or (Index >= FCount) then  
  161.     Error(@SListIndexError, Index);  
  162. Temp :Items[Index];  
  163. Dec(FCount);  
  164. if Index < FCount then  
  165.     System.Move(FList^[Index + 1], FList^[Index],  
  166.       (FCount - Index) * SizeOf(Pointer));  
  167. if Temp <> nil then  
  168.     Notify(Temp, lnDeleted);  
  169. end;  
  170.  
  171. // 俩个位置的数据交换  
  172. procedure TList.Exchange(Index1, Index2: Integer);  
  173. var  
  174. Item: Pointer;  
  175. begin  
  176. if (Index1 < 0) or (Index1 >= FCount) then  
  177.     Error(@SListIndexError, Index1);  
  178. if (Index2 < 0) or (Index2 >= FCount) then  
  179.     Error(@SListIndexError, Index2);  
  180. Item :FList^[Index1];  
  181. FList^[Index1] :FList^[Index2];  
  182. FList^[Index2] :Item;  
  183. end;  
  184.  
  185. // 先判断是否需要扩大内存分配,然后返回LIST自身  
  186. function TList.Expand: TList;  
  187. begin  
  188. if FCount = FCapacity then  
  189.     Grow;  
  190. Result :Self;  
  191. end;  
  192.  
  193. // 删除数据,同时将要删除的数据返回  
  194. function TList.Extract(Item: Pointer): Pointer;  
  195. var  
  196. I: Integer;  
  197. begin  
  198. Result :nil;  
  199. :IndexOf(Item);  
  200. if I >= 0 then  
  201. begin  
  202.     Result :Item;  
  203.     FList^[I] :nil;  
  204.     Delete(I);  
  205.     Notify(Result, lnExtracted);  
  206. end;  
  207. end;  
  208.  
  209. // 返回首个位置的数据  
  210. function TList.First: Pointer;  
  211. begin  
  212. Result :Get(0);  
  213. end;  
  214.  
  215. // 插入数据,同时将要插入的位置的数据都往后挪一个位置  
  216. procedure TList.Insert(Index: Integer; Item: Pointer);  
  217. begin  
  218. if (Index < 0) or (Index > FCount) then  
  219.     Error(@SListIndexError, Index);  
  220. if FCount = FCapacity then  
  221.     Grow;  
  222. if Index < FCount then  
  223.     System.Move(FList^[Index], FList^[Index + 1],  
  224.       (FCount - Index) * SizeOf(Pointer));  
  225. FList^[Index] :Item;  
  226. Inc(FCount);  
  227. if Item <> nil then  
  228.     Notify(Item, lnAdded);  
  229. end;  
  230.  
  231. // 获得最后一个位置的数据  
  232. function TList.Last: Pointer;  
  233. begin  
  234. Result :Get(FCount - 1);  
  235. end;  
  236.  
  237. // 将CurIndex的数据在NewIndex位置插入,同时将CurIndex位置数据删除  
  238. procedure TList.Move(CurIndex, NewIndex: Integer);  
  239. var  
  240. Item: Pointer;  
  241. begin  
  242. if CurIndex <> NewIndex then  
  243. begin  
  244.     if (NewIndex < 0) or (NewIndex >= FCount) then  
  245.       Error(@SListIndexError, NewIndex);  
  246.     Item :Get(CurIndex);  
  247.     FList^[CurIndex] :nil;  
  248.     Delete(CurIndex);  
  249.     Insert(NewIndex, nil);  
  250.     FList^[NewIndex] :Item;  
  251. end;  
  252. end;  
  253.  
  254. // 根据传入的Item 删除对应位置的数据   
  255. function TList.Remove(Item: Pointer): Integer;  
  256. begin  
  257. Result :IndexOf(Item);  
  258. if Result >= 0 then  
  259.     Delete(Result);  
  260. end;  
  261.  
  262. // 清理作用,将数组中为nil 的数据清除  
  263. procedure TList.Pack;  
  264. var  
  265. I: Integer;  
  266. begin  
  267. for I :FCount - 1 downto 0 do  
  268.     if Items[I] = nil then  
  269.       Delete(I);  
  270. end;  
  271.  
  272. // 标准的快速排序,同时传入 TListSortCompare类型的Compare函数指针来作为交换函数   
  273. procedure TList.Sort(Compare: TListSortCompare);  
  274. begin  
  275. if (FList <> nil) and (Count > 0) then  
  276.     QuickSort(FList, 0, Count - 1, Compare);  
  277. end;  
  278.  
  279. //  
  280. TList类实现了一个带缺省参数的方法procedure Assign(ListA: TList; AOperator: TListAssignOp = laCopy; ListB: TList = nil),  
  281.  
  282. 如果ListB不为空, 临时变量LSource :ListB;,则递归,Assign(ListA);默认参数 laCopy, ListB: TList = nil 
  283. 递归函数操作(LSource :ListA, 清空List, 然后将ListA 拷贝到list中)  
  284. 执行递归函数后, 然后根据AOperator和ListB进行各类运算  
  285.  
  286. 如果ListB为空,则根据AOperator将self和ListA进行各类运算。  
  287.  
  288. procedure TList.Assign(ListA: TList; AOperator: TListAssignOp; ListB: TList);  
  289. var  
  290. I: Integer;  
  291. LTemp, LSource: TList;  
  292. begin  
  293. // ListB given?  
  294. if ListB <> nil then  
  295. begin  
  296.     LSource :ListB;  
  297.     Assign(ListA);  
  298. end  
  299. else  
  300.     LSource :ListA;  
  301.  
  302. // on with the show  
  303. case AOperator of  
  304.  
  305.     // 12345, 346346 = 346 : only those in the new list  
  306.     laCopy:  
  307.       begin  
  308.         Clear;  
  309.         Capacity :LSource.Capacity;  
  310.         for I :0 to LSource.Count - 1 do  
  311.           Add(LSource[I]);  
  312.       end;  
  313.  
  314.     // 12345, 34346 = 34 : intersection of the two lists  
  315.     laAnd:  
  316.       for I :Count - 1 downto 0 do  
  317.         if LSource.IndexOf(Items[I]) = -1 then  
  318.           Delete(I);  
  319.  
  320.     // 12345, 346 = 123456 : union of the two lists  
  321.     laOr:  
  322.       for I :0 to LSource.Count - 1 do  
  323.         if IndexOf(LSource[I]) = -1 then  
  324.           Add(LSource[I]);  
  325.  
  326.     // 12345, 346 = 1256 : only those not in both lists  
  327.     laXor:  
  328.       begin  
  329.         LTemp :TList.Create; // Temp holder of 4 byte values  
  330.         try  
  331.           LTemp.Capacity :LSource.Count;  
  332.           for I :0 to LSource.Count - 1 do  
  333.             if IndexOf(LSource[I]) = -1 then  
  334.               LTemp.Add(LSource[I]);  
  335.           for I :Count - 1 downto 0 do  
  336.             if LSource.IndexOf(Items[I]) <> -1 then  
  337.               Delete(I);  
  338.           I :Count + LTemp.Count;  
  339.           if Capacity < I then  
  340.             Capacity :I;  
  341.           for I :0 to LTemp.Count - 1 do  
  342.             Add(LTemp[I]);  
  343.         finally  
  344.           LTemp.Free;  
  345.         end;  
  346.       end;  
  347.  
  348.     // 12345, 346 = 125 : only those unique to source  
  349.     laSrcUnique:  
  350.       for I :Count - 1 downto 0 do  
  351.         if LSource.IndexOf(Items[I]) <> -1 then  
  352.           Delete(I);  
  353.  
  354.     // 12345, 346 = 6 : only those unique to dest  
  355.     laDestUnique:  
  356.       begin  
  357.         LTemp :TList.Create;  
  358.         try  
  359.           LTemp.Capacity :LSource.Count;  
  360.           for I :LSource.Count - 1 downto 0 do  
  361.             if IndexOf(LSource[I]) = -1 then  
  362.               LTemp.Add(LSource[I]);  
  363.           Assign(LTemp);  
  364.         finally  
  365.           LTemp.Free;  
  366.         end;  
  367.       end;  
  368. end;  
  369. end;  
  370.  
  371. // 在数组中做循环,从低到高,判断是否有和 Item 相等的,如果相等则返回索引,无则返回 -1   
  372. function TList.IndexOf(Item: Pointer): Integer;  
  373. begin  
  374. Result :0;  
  375. while (Result < FCount) and (FList^[Result] <> Item) do  
  376.     Inc(Result);  
  377. if Result = FCount then  
  378.     Result := -1;  
  379. end;  
  380.