java 遍历 likedlist_介绍ArrayList和LinkedList的五种遍历方式,各种的性能对比,根据ArrayList和LinkedList的实现分析结果,总结结论...

主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论。

通过本文你可以了解(1)List的五种遍历方式及各自性能 (2)foreach及Iterator的实现 (3)加深对ArrayList和LinkedList实现的了解。

阅读本文前希望你已经了解ArrayList顺序存储和LinkedList链式的结构,本文不对此进行介绍。

1. List的五种遍历方式

下面只是简单介绍各种遍历示例(以ArrayList为例),各自优劣会在本文后面进行分析给出结论。

(1) for each循环

Java

List list = new ArrayList();

for (Integer j : list) {

// use j

}

1

2

3

4

Listlist=newArrayList();

for(Integerj:list){

// use j

}

(2) 显示调用集合迭代器

Java

List list = new ArrayList();

for (Iterator iterator = list.iterator(); iterator.hasNext();) {

iterator.next();

}

1

2

3

4

Listlist=newArrayList();

for(Iteratoriterator=list.iterator();iterator.hasNext();){

iterator.next();

}

Java

List list = new ArrayList();

Iterator iterator = list.iterator();

while (iterator.hasNext()) {

iterator.next();

}

1

2

3

4

5

Listlist=newArrayList();

Iteratoriterator=list.iterator();

while(iterator.hasNext()){

iterator.next();

}

(3) 下标递增循环,终止条件为每次调用size()函数比较判断

Java

List list = new ArrayList();

for (int j = 0; j < list.size(); j++) {

list.get(j);

}

1

2

3

4

Listlist=newArrayList();

for(intj=0;j

list.get(j);

}

(4) 下标递增循环,终止条件为和等于size()的临时变量比较判断

Java

List list = new ArrayList();

int size = list.size();

for (int j = 0; j < size; j++) {

list.get(j);

}

1

2

3

4

5

Listlist=newArrayList();

intsize=list.size();

for(intj=0;j

list.get(j);

}

(5) 下标递减循环

Java

List list = new ArrayList();

for (int j = list.size() - 1; j >= 0; j--) {

list.get(j);

}

1

2

3

4

Listlist=newArrayList();

for(intj=list.size()-1;j>=0;j--){

list.get(j);

}

在测试前大家可以根据对ArrayList和LinkedList数据结构及Iterator的了解,想想上面五种遍历方式哪个性能更优。

2、List五种遍历方式的性能测试及对比

以下是性能测试代码,会输出不同数量级大小的ArrayList和LinkedList各种遍历方式所花费的时间。

ArrayList和LinkedList循环性能对比测试代码

Java

package cn.trinea.java.test;

import java.text.DecimalFormat;

import java.util.ArrayList;

import java.util.Calendar;

import java.util.Iterator;

import java.util.LinkedList;

import java.util.List;

/**

* JavaLoopTest

*

* @author www.trinea.cn 2013-10-28

*/

public class JavaLoopTest {

public static void main(String[] args) {

System.out.print("compare loop performance of ArrayList");

loopListCompare(getArrayLists(10000, 100000, 1000000, 9000000));

System.out.print("\r\n\r\ncompare loop performance of LinkedList");

loopListCompare(getLinkedLists(100, 1000, 10000, 100000));

}

public static List[] getArrayLists(int... sizeArray) {

List[] listArray = new ArrayList[sizeArray.length];

for (int i = 0; i < listArray.length; i++) {

int size = sizeArray[i];

List list = new ArrayList();

for (int j = 0; j < size; j++) {

list.add(j);

}

listArray[i] = list;

}

return listArray;

}

public static List[] getLinkedLists(int... sizeArray) {

List[] listArray = new LinkedList[sizeArray.length];

for (int i = 0; i < listArray.length; i++) {

int size = sizeArray[i];

List list = new LinkedList();

for (int j = 0; j < size; j++) {

list.add(j);

}

listArray[i] = list;

}

return listArray;

}

public static void loopListCompare(List... listArray) {

printHeader(listArray);

long startTime, endTime;

// Type 1

for (int i = 0; i < listArray.length; i++) {

List list = listArray[i];

startTime = Calendar.getInstance().getTimeInMillis();

for (Integer j : list) {

// use j

}

endTime = Calendar.getInstance().getTimeInMillis();

printCostTime(i, listArray.length, "for each", endTime - startTime);

}

// Type 2

for (int i = 0; i < listArray.length; i++) {

List list = listArray[i];

startTime = Calendar.getInstance().getTimeInMillis();

// Iterator iterator = list.iterator();

// while(iterator.hasNext()) {

// iterator.next();

// }

for (Iterator iterator = list.iterator(); iterator.hasNext();) {

iterator.next();

}

endTime = Calendar.getInstance().getTimeInMillis();

printCostTime(i, listArray.length, "for iterator", endTime - startTime);

}

// Type 3

for (int i = 0; i < listArray.length; i++) {

List list = listArray[i];

startTime = Calendar.getInstance().getTimeInMillis();

for (int j = 0; j < list.size(); j++) {

list.get(j);

}

endTime = Calendar.getInstance().getTimeInMillis();

printCostTime(i, listArray.length, "for list.size()", endTime - startTime);

}

// Type 4

for (int i = 0; i < listArray.length; i++) {

List list = listArray[i];

startTime = Calendar.getInstance().getTimeInMillis();

int size = list.size();

for (int j = 0; j < size; j++) {

list.get(j);

}

endTime = Calendar.getInstance().getTimeInMillis();

printCostTime(i, listArray.length, "for size = list.size()", endTime - startTime);

}

// Type 5

for (int i = 0; i < listArray.length; i++) {

List list = listArray[i];

startTime = Calendar.getInstance().getTimeInMillis();

for (int j = list.size() - 1; j >= 0; j--) {

list.get(j);

}

endTime = Calendar.getInstance().getTimeInMillis();

printCostTime(i, listArray.length, "for j--", endTime - startTime);

}

}

static int FIRST_COLUMN_LENGTH = 23, OTHER_COLUMN_LENGTH = 12, TOTAL_COLUMN_LENGTH = 71;

static final DecimalFormat COMMA_FORMAT = new DecimalFormat("#,###");

public static void printHeader(List... listArray) {

printRowDivider();

for (int i = 0; i < listArray.length; i++) {

if (i == 0) {

StringBuilder sb = new StringBuilder().append("list size");

while (sb.length() < FIRST_COLUMN_LENGTH) {

sb.append(" ");

}

System.out.print(sb);

}

StringBuilder sb = new StringBuilder().append("| ").append(COMMA_FORMAT.format(listArray[i].size()));

while (sb.length() < OTHER_COLUMN_LENGTH) {

sb.append(" ");

}

System.out.print(sb);

}

TOTAL_COLUMN_LENGTH = FIRST_COLUMN_LENGTH + OTHER_COLUMN_LENGTH * listArray.length;

printRowDivider();

}

public static void printRowDivider() {

System.out.println();

StringBuilder sb = new StringBuilder();

while (sb.length() < TOTAL_COLUMN_LENGTH) {

sb.append("-");

}

System.out.println(sb);

}

public static void printCostTime(int i, int size, String caseName, long costTime) {

if (i == 0) {

StringBuilder sb = new StringBuilder().append(caseName);

while (sb.length() < FIRST_COLUMN_LENGTH) {

sb.append(" ");

}

System.out.print(sb);

}

StringBuilder sb = new StringBuilder().append("| ").append(costTime).append(" ms");

while (sb.length() < OTHER_COLUMN_LENGTH) {

sb.append(" ");

}

System.out.print(sb);

if (i == size - 1) {

printRowDivider();

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

packagecn.trinea.java.test;

importjava.text.DecimalFormat;

importjava.util.ArrayList;

importjava.util.Calendar;

importjava.util.Iterator;

importjava.util.LinkedList;

importjava.util.List;

/**

* JavaLoopTest

*

* @author www.trinea.cn 2013-10-28

*/

publicclassJavaLoopTest{

publicstaticvoidmain(String[]args){

System.out.print("compare loop performance of ArrayList");

loopListCompare(getArrayLists(10000,100000,1000000,9000000));

System.out.print("\r\n\r\ncompare loop performance of LinkedList");

loopListCompare(getLinkedLists(100,1000,10000,100000));

}

publicstaticList[]getArrayLists(int...sizeArray){

List[]listArray=newArrayList[sizeArray.length];

for(inti=0;i

intsize=sizeArray[i];

Listlist=newArrayList();

for(intj=0;j

list.add(j);

}

listArray[i]=list;

}

returnlistArray;

}

publicstaticList[]getLinkedLists(int...sizeArray){

List[]listArray=newLinkedList[sizeArray.length];

for(inti=0;i

intsize=sizeArray[i];

Listlist=newLinkedList();

for(intj=0;j

list.add(j);

}

listArray[i]=list;

}

returnlistArray;

}

publicstaticvoidloopListCompare(List...listArray){

printHeader(listArray);

longstartTime,endTime;

// Type 1

for(inti=0;i

Listlist=listArray[i];

startTime=Calendar.getInstance().getTimeInMillis();

for(Integerj:list){

// use j

}

endTime=Calendar.getInstance().getTimeInMillis();

printCostTime(i,listArray.length,"for each",endTime-startTime);

}

// Type 2

for(inti=0;i

Listlist=listArray[i];

startTime=Calendar.getInstance().getTimeInMillis();

// Iterator iterator = list.iterator();

// while(iterator.hasNext()) {

// iterator.next();

// }

for(Iteratoriterator=list.iterator();iterator.hasNext();){

iterator.next();

}

endTime=Calendar.getInstance().getTimeInMillis();

printCostTime(i,listArray.length,"for iterator",endTime-startTime);

}

// Type 3

for(inti=0;i

Listlist=listArray[i];

startTime=Calendar.getInstance().getTimeInMillis();

for(intj=0;j

list.get(j);

}

endTime=Calendar.getInstance().getTimeInMillis();

printCostTime(i,listArray.length,"for list.size()",endTime-startTime);

}

// Type 4

for(inti=0;i

Listlist=listArray[i];

startTime=Calendar.getInstance().getTimeInMillis();

intsize=list.size();

for(intj=0;j

list.get(j);

}

endTime=Calendar.getInstance().getTimeInMillis();

printCostTime(i,listArray.length,"for size = list.size()",endTime-startTime);

}

// Type 5

for(inti=0;i

Listlist=listArray[i];

startTime=Calendar.getInstance().getTimeInMillis();

for(intj=list.size()-1;j>=0;j--){

list.get(j);

}

endTime=Calendar.getInstance().getTimeInMillis();

printCostTime(i,listArray.length,"for j--",endTime-startTime);

}

}

staticintFIRST_COLUMN_LENGTH=23,OTHER_COLUMN_LENGTH=12,TOTAL_COLUMN_LENGTH=71;

staticfinalDecimalFormatCOMMA_FORMAT=newDecimalFormat("#,###");

publicstaticvoidprintHeader(List...listArray){

printRowDivider();

for(inti=0;i

if(i==0){

StringBuildersb=newStringBuilder().append("list size");

while(sb.length()

sb.append(" ");

}

System.out.print(sb);

}

StringBuildersb=newStringBuilder().append("| ").append(COMMA_FORMAT.format(listArray[i].size()));

while(sb.length()

sb.append(" ");

}

System.out.print(sb);

}

TOTAL_COLUMN_LENGTH=FIRST_COLUMN_LENGTH+OTHER_COLUMN_LENGTH*listArray.length;

printRowDivider();

}

publicstaticvoidprintRowDivider(){

System.out.println();

StringBuildersb=newStringBuilder();

while(sb.length()

sb.append("-");

}

System.out.println(sb);

}

publicstaticvoidprintCostTime(inti,intsize,StringcaseName,longcostTime){

if(i==0){

StringBuildersb=newStringBuilder().append(caseName);

while(sb.length()

sb.append(" ");

}

System.out.print(sb);

}

StringBuildersb=newStringBuilder().append("| ").append(costTime).append(" ms");

while(sb.length()

sb.append(" ");

}

System.out.print(sb);

if(i==size-1){

printRowDivider();

}

}

}

PS:如果运行报异常in thread “main” java.lang.OutOfMemoryError: Java heap space,请将main函数里面list size的大小减小。

其中getArrayLists函数会返回不同size的ArrayList,getLinkedLists函数会返回不同size的LinkedList。

loopListCompare函数会分别用上面的遍历方式1-5去遍历每一个list数组(包含不同大小list)中的list。

print开头函数为输出辅助函数。

测试环境为Windows7 32位系统 3.2G双核CPU 4G内存,Java 7,Eclipse -Xms512m -Xmx512m

最终测试结果如下:

compare loop performance of ArrayList

-----------------------------------------------------------------------

list size | 10,000 | 100,000 | 1,000,000 | 10,000,000

-----------------------------------------------------------------------

for each | 1 ms | 3 ms | 14 ms | 152 ms

-----------------------------------------------------------------------

for iterator | 0 ms | 1 ms | 12 ms | 114 ms

-----------------------------------------------------------------------

for list.size() | 1 ms | 1 ms | 13 ms | 128 ms

-----------------------------------------------------------------------

for size = list.size() | 0 ms | 0 ms | 6 ms | 62 ms

-----------------------------------------------------------------------

for j-- | 0 ms | 1 ms | 6 ms | 63 ms

-----------------------------------------------------------------------

compare loop performance of LinkedList

-----------------------------------------------------------------------

list size | 100 | 1,000 | 10,000 | 100,000

-----------------------------------------------------------------------

for each | 0 ms | 1 ms | 1 ms | 2 ms

-----------------------------------------------------------------------

for iterator | 0 ms | 0 ms | 0 ms | 2 ms

-----------------------------------------------------------------------

for list.size() | 0 ms | 1 ms | 73 ms | 7972 ms

-----------------------------------------------------------------------

for size = list.size() | 0 ms | 0 ms | 67 ms | 8216 ms

-----------------------------------------------------------------------

for j-- | 0 ms | 1 ms | 67 ms | 8277 ms

-----------------------------------------------------------------------

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

compareloopperformanceofArrayList

-----------------------------------------------------------------------

listsize|10,000|100,000|1,000,000|10,000,000

-----------------------------------------------------------------------

foreach|1ms|3ms|14ms|152ms

-----------------------------------------------------------------------

foriterator|0ms|1ms|12ms|114ms

-----------------------------------------------------------------------

forlist.size()|1ms|1ms|13ms|128ms

-----------------------------------------------------------------------

forsize=list.size()|0ms|0ms|6ms|62ms

-----------------------------------------------------------------------

forj--|0ms|1ms|6ms|63ms

-----------------------------------------------------------------------

compareloopperformanceofLinkedList

-----------------------------------------------------------------------

listsize|100|1,000|10,000|100,000

-----------------------------------------------------------------------

foreach|0ms|1ms|1ms|2ms

-----------------------------------------------------------------------

foriterator|0ms|0ms|0ms|2ms

-----------------------------------------------------------------------

forlist.size()|0ms|1ms|73ms|7972ms

-----------------------------------------------------------------------

forsize=list.size()|0ms|0ms|67ms|8216ms

-----------------------------------------------------------------------

forj--|0ms|1ms|67ms|8277ms

-----------------------------------------------------------------------

第一张表为ArrayList对比结果,第二张表为LinkedList对比结果。

表横向为同一遍历方式不同大小list遍历的时间消耗,纵向为同一list不同遍历方式遍历的时间消耗。

PS:由于首次遍历List会稍微多耗时一点,for each的结果稍微有点偏差,将测试代码中的几个Type顺序调换会发现,for each耗时和for iterator接近。

3、遍历方式性能测试结果分析

(1) foreach介绍

foreach是Java SE5.0引入的功能很强的循环结构,for (Integer j : list)应读作for each int in list。

for (Integer j : list)实现几乎等价于

Java

Iterator iterator = list.iterator();

while(iterator.hasNext()) {

Integer j = iterator.next();

}

1

2

3

4

Iteratoriterator=list.iterator();

while(iterator.hasNext()){

Integerj=iterator.next();

}

下面的分析会将foreach和显示调用集合迭代器两种遍历方式归类为Iterator方式,其他三种称为get方式遍历。

这时我们已经发现foreach的一大好处,简单一行实现了四行的功能,使得代码简洁美观,另一大好处是相对于下标循环而言的,foreach不必关心下标初始值和终止值及越界等,所以不易出错。Effective-Java中推荐使用此种写法遍历,本文会验证这个说法。

使用foreach结构的类对象必须实现了Iterable接口,Java的Collection继承自此接口,List实现了Collection,这个接口仅包含一个函数,源码如下:

Java

package java.lang;

import java.util.Iterator;

/**

* Implementing this interface allows an object to be the target of

* the "foreach" statement.

*

* @param the type of elements returned by the iterator

*

* @since 1.5

*/

public interface Iterable {

/**

* Returns an iterator over a set of elements of type T.

*

* @return an Iterator.

*/

Iterator iterator();

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

packagejava.lang;

importjava.util.Iterator;

/**

* Implementing this interface allows an object to be the target of

* the "foreach" statement.

*

* @param the type of elements returned by the iterator

*

* @since 1.5

*/

publicinterfaceIterable{

/**

* Returns an iterator over a set of elements of type T.

*

* @return an Iterator.

*/

Iteratoriterator();

}

iterator()用于返回一个Iterator,从foreach的等价实现中我们可以看到,会调用这个函数得到Iterator,再通过Iterator的next()得到下一个元素,hasNext()判断是否还有更多元素。Iterator源码如下:

Java

public interface Iterator {

boolean hasNext();

E next();

void remove();

}

1

2

3

4

5

6

7

publicinterfaceIterator{

booleanhasNext();

Enext();

voidremove();

}

(2) ArrayList遍历方式结果分析

compare loop performance of ArrayList

-----------------------------------------------------------------------

list size | 10,000 | 100,000 | 1,000,000 | 10,000,000

-----------------------------------------------------------------------

for each | 1 ms | 3 ms | 14 ms | 152 ms

-----------------------------------------------------------------------

for iterator | 0 ms | 1 ms | 12 ms | 114 ms

-----------------------------------------------------------------------

for list.size() | 1 ms | 1 ms | 13 ms | 128 ms

-----------------------------------------------------------------------

for size = list.size() | 0 ms | 0 ms | 6 ms | 62 ms

-----------------------------------------------------------------------

for j-- | 0 ms | 1 ms | 6 ms | 63 ms

-----------------------------------------------------------------------

1

2

3

4

5

6

7

8

9

10

11

12

13

14

compareloopperformanceofArrayList

-----------------------------------------------------------------------

listsize|10,000|100,000|1,000,000|10,000,000

-----------------------------------------------------------------------

foreach|1ms|3ms|14ms|152ms

-----------------------------------------------------------------------

foriterator|0ms|1ms|12ms|114ms

-----------------------------------------------------------------------

forlist.size()|1ms|1ms|13ms|128ms

-----------------------------------------------------------------------

forsize=list.size()|0ms|0ms|6ms|62ms

-----------------------------------------------------------------------

forj--|0ms|1ms|6ms|63ms

-----------------------------------------------------------------------

PS:由于首次遍历List会稍微多耗时一点,for each的结果稍微有点偏差,将测试代码中的几个Type顺序调换会发现,for each耗时和for iterator接近。

从上面我们可以看出:

a. 在ArrayList大小为十万之前,五种遍历方式时间消耗几乎一样

b. 在十万以后,第四、五种遍历方式快于前三种,get方式优于Iterator方式,并且

Java

int size = list.size();

for (int j = 0; j < size; j++) {

list.get(j);

}

1

2

3

4

intsize=list.size();

for(intj=0;j

list.get(j);

}

用临时变量size取代list.size()性能更优。我们看看ArrayList中迭代器Iterator和get方法的实现

Java

private class Itr implements Iterator {

int cursor; // index of next element to return

int lastRet = -1; // index of last element returned; -1 if no such

int expectedModCount = modCount;

public boolean hasNext() {

return cursor != size;

}

@SuppressWarnings("unchecked")

public E next() {

checkForComodification();

int i = cursor;

if (i >= size)

throw new NoSuchElementException();

Object[] elementData = ArrayList.this.elementData;

if (i >= elementData.length)

throw new ConcurrentModificationException();

cursor = i + 1;

return (E) elementData[lastRet = i];

}

……

}

public E get(int index) {

rangeCheck(index);

return elementData(index);

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

privateclassItrimplementsIterator{

intcursor;// index of next element to return

intlastRet=-1;// index of last element returned; -1 if no such

intexpectedModCount=modCount;

publicbooleanhasNext(){

returncursor!=size;

}

@SuppressWarnings("unchecked")

publicEnext(){

checkForComodification();

inti=cursor;

if(i>=size)

thrownewNoSuchElementException();

Object[]elementData=ArrayList.this.elementData;

if(i>=elementData.length)

thrownewConcurrentModificationException();

cursor=i+1;

return(E)elementData[lastRet=i];

}

……

}

publicEget(intindex){

rangeCheck(index);

returnelementData(index);

}

从中可以看出get和Iterator的next函数同样通过直接定位数据获取元素,只是多了几个判断而已。

c . 从上可以看出即便在千万大小的ArrayList中,几种遍历方式相差也不过50ms左右,且在常用的十万左右时间几乎相等,考虑foreach的优点,我们大可选用foreach这种简便方式进行遍历。

(3) LinkedList遍历方式结果分析

compare loop performance of LinkedList

-----------------------------------------------------------------------

list size | 100 | 1,000 | 10,000 | 100,000

-----------------------------------------------------------------------

for each | 0 ms | 1 ms | 1 ms | 2 ms

-----------------------------------------------------------------------

for iterator | 0 ms | 0 ms | 0 ms | 2 ms

-----------------------------------------------------------------------

for list.size() | 0 ms | 1 ms | 73 ms | 7972 ms

-----------------------------------------------------------------------

for size = list.size() | 0 ms | 0 ms | 67 ms | 8216 ms

-----------------------------------------------------------------------

for j-- | 0 ms | 1 ms | 67 ms | 8277 ms

-----------------------------------------------------------------------

1

2

3

4

5

6

7

8

9

10

11

12

13

14

compareloopperformanceofLinkedList

-----------------------------------------------------------------------

listsize|100|1,000|10,000|100,000

-----------------------------------------------------------------------

foreach|0ms|1ms|1ms|2ms

-----------------------------------------------------------------------

foriterator|0ms|0ms|0ms|2ms

-----------------------------------------------------------------------

forlist.size()|0ms|1ms|73ms|7972ms

-----------------------------------------------------------------------

forsize=list.size()|0ms|0ms|67ms|8216ms

-----------------------------------------------------------------------

forj--|0ms|1ms|67ms|8277ms

-----------------------------------------------------------------------

PS:由于首次遍历List会稍微多耗时一点,for each的结果稍微有点偏差,将测试代码中的几个Type顺序调换会发现,for each耗时和for iterator接近。

从上面我们可以看出:

a 在LinkedList大小接近一万时,get方式和Iterator方式就已经差了差不多两个数量级,十万时Iterator方式性能已经远胜于get方式。

我们看看LinkedList中迭代器和get方法的实现

Java

private class ListItr implements ListIterator {

private Node lastReturned = null;

private Node next;

private int nextIndex;

private int expectedModCount = modCount;

ListItr(int index) {

// assert isPositionIndex(index);

next = (index == size) ? null : node(index);

nextIndex = index;

}

public boolean hasNext() {

return nextIndex < size;

}

public E next() {

checkForComodification();

if (!hasNext())

throw new NoSuchElementException();

lastReturned = next;

next = next.next;

nextIndex++;

return lastReturned.item;

}

……

}

public E get(int index) {

checkElementIndex(index);

return node(index).item;

}

/**

* Returns the (non-null) Node at the specified element index.

*/

Node node(int index) {

// assert isElementIndex(index);

if (index < (size >> 1)) {

Node x = first;

for (int i = 0; i < index; i++)

x = x.next;

return x;

} else {

Node x = last;

for (int i = size - 1; i > index; i--)

x = x.prev;

return x;

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

privateclassListItrimplementsListIterator{

privateNodelastReturned=null;

privateNodenext;

privateintnextIndex;

privateintexpectedModCount=modCount;

ListItr(intindex){

// assert isPositionIndex(index);

next=(index==size)?null:node(index);

nextIndex=index;

}

publicbooleanhasNext(){

returnnextIndex

}

publicEnext(){

checkForComodification();

if(!hasNext())

thrownewNoSuchElementException();

lastReturned=next;

next=next.next;

nextIndex++;

returnlastReturned.item;

}

……

}

publicEget(intindex){

checkElementIndex(index);

returnnode(index).item;

}

/**

* Returns the (non-null) Node at the specified element index.

*/

Nodenode(intindex){

// assert isElementIndex(index);

if(index>1)){

Nodex=first;

for(inti=0;i

x=x.next;

returnx;

}else{

Nodex=last;

for(inti=size-1;i>index;i--)

x=x.prev;

returnx;

}

}

从上面代码中可以看出LinkedList迭代器的next函数只是通过next指针快速得到下一个元素并返回。而get方法会从头遍历直到index下标,查找一个元素时间复杂度为哦O(n),遍历的时间复杂度就达到了O(n2)。

所以对于LinkedList的遍历推荐使用foreach,避免使用get方式遍历。

(4) ArrayList和LinkedList遍历方式结果对比分析

从上面的数量级来看,同样是foreach循环遍历,ArrayList和LinkedList时间差不多,可将本例稍作修改加大list size会发现两者基本在一个数量级上。

但ArrayList get函数直接定位获取的方式时间复杂度为O(1),而LinkedList的get函数时间复杂度为O(n)。

再结合考虑空间消耗的话,建议首选ArrayList。对于个别插入删除非常多的可以使用LinkedList。

4、结论总结

通过上面的分析我们基本可以总结下:

(1) 无论ArrayList还是LinkedList,遍历建议使用foreach,尤其是数据量较大时LinkedList避免使用get遍历。

(2) List使用首选ArrayList。对于个别插入删除非常多的可以使用LinkedList。

(3) 可能在遍历List循环内部需要使用到下标,这时综合考虑下是使用foreach和自增count还是get方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值