数据列表List

数据列表List是Java提供的另一种数据集合类型,允许用户按顺序存储/操作多个数据。List里可以存储任何类型的数据(包括对象),但是需要是同一类别。

1. 创建List

List<String> names = new ArrayList<>();

注意.

  • 这里names的类型是List,一个Java接口。等号右边是通过ArrayList类创建具体的列表类型;
  • List<String> 尖括号<>里声明了List里可以存储元素的类型,这里是字符串String。而右边的尖括号里可以写上String,也可以不写;
  • 这里可以理解为<>是一个附加规定(列表里存储元素的类型),删掉<>也可以运行,但是不安全。

2. 向列表里添加数据 add(element)

names.add("John");
names.add("Mary");
names.add("Bob");

注.

  • 列表里元素的顺序与其添加进去的顺序一致。

3. 获取列表数据 get(index)

String firstElement = names.get(0); // 获取列表里第一个元素
String lastElement = names.get(names.size() - 1);  // 获取最后一个元素

注.

  • List的下标也是从0开始的。

4. 删除列表里的单个元素 remove(index)

names.remove(1);  // 从列表里删除下标为1的元素(第二个)

5. 获取列表大小 size()

int numNames = names.size(); 

6. 循环整个List

for(String name : names) {
    System.out.println(name);
}

或者

for(int i = 0; i < names.size(); i++) {
    System.out.println(names.get(i));
}

此处跟Array操作类似,区别在于需要使用names.size()获取names列表的大小。

7. 向现有列表特定位置添加元素 add(position, element)

names.add(1, "Tom");

这里将“Tom”添加到names列表的第二个位置.

8. 修改某个位置的元素 set(index, element)

names.set(1, "Nio"); // 将第二个位置的元素修改为Nio

9. 判断列表是否包含某元素 contains(element)

boolean hasName = names.contains("Tom"); // names里是否有元素Tom,这里返回值应该是true

10. 判断列表是否为空 isEmpty()

boolean isNameEmpty = names.isEmpty();

11. 查找某个元素的下标 indexOf(element)

int indexOfTom = names.indexOf("Tom");

注. 如果names列表中包含Tom,则返回所在index;如果不包含Tom,则返回-1.

12. 获取子列表 subList(fromIndex, toIndex)

List<String> subNames = names.subList(0, 2); // 第一个到第三个元素构成的子列表

13. 清空列表

names.clear();

14. 将列表2的元素全部添加到列表1 list1.addAll(list2)

List<String> newNames = new ArrayList<>();
newNames.add("Jessi");
newNames.add("Ame");

names.addAll(newNames);

15. 从列表1中移除列表2中的所有元素 list1.removeAll(list2)

names.removeAll(newNames);

16. 其他注意事项

  • 列表是可变长度的;
  • 可以从官方文档查看List提供的更多方法;
  • 如果要一次在列表的不同位置移除或添加多个元素不能直接循环使用remove(index)方法!

例.

  • 创建列表strs 并添加元素s1到s5
import java.util.ArrayList;
import java.util.List;

public class ArrayExample {
	public static void main(String[] args) {
		List<String> strs = new ArrayList<>();
		strs.add("s1");
		strs.add("s2");
		strs.add("s3");
		strs.add("s4");
		strs.add("s5");
		System.out.println(strs);
	}
}
  • 假定想要移除第一个和第二个元素s1和s2,如果按照下面的写法将会出错。
import java.util.ArrayList;
import java.util.List;

public class ArrayExample {
	public static void main(String[] args) {
		List<String> strs = new ArrayList<>();
		strs.add("s1");
		strs.add("s2");
		strs.add("s3");
		strs.add("s4");
		strs.add("s5");
        for (int i = 0; i <= 1; i++) {
		strs.remove(i);
        }
		System.out.println(strs);
	}
}

运行结果

[s2, s4, s5]

这里我们发现:被移除的是s1和s3,和预计的不一样。因为

  • 当i=0进入循环后,strs.remove(0)将会移除第一个位置上的元素,然后s2变成了第一个元素,s3变成了第二个元素;
  • 当进入第二轮循环i=1时,strs.remove(1)实际会移除当前处在第二个位置的元素s3。

正确做法:使用迭代器Iterator。迭代器会在循环结束之前保持每个元素下标不变

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ArrayExample {
	public static void main(String[] args) {
		List<String> strs = new ArrayList<>();
		strs.add("s1");
		strs.add("s2");
		strs.add("s3");
		strs.add("s4");
		strs.add("s5");
		Iterator<String> it = strs.iterator();  // 通过strs创建迭代器
		for (int i = 0; i <= 1; i++) {
			it.next(); 
			it.remove();
		}
			System.out.println(strs);

	}
}

运行结果

[s3, s4, s5]

说明

  • iterator会维护一个游标,初始状态游标没有指向任何元素;
  • iterator.next()方法会将游标向下移动,第一次移动时会指向列表的第一个元素;
  • iterator.remove()方法会移除当前游标所在位置的元素,但是会留一个空,保持后续的元素下标不变!
  • 执行完后,iterator会删除所有的空,留下一个我们想要的列表。

通常的迭代器的用法如下,假设我们想删除 所有 的s3,而我们不知道它们的位置

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ArrayExample {
	public static void main(String[] args) {
		List<String> strs = new ArrayList<>();
		strs.add("s1");
		strs.add("s2");
		strs.add("s3");
		strs.add("s4");
        strs.add("s3");    // 添加第二个s3
		strs.add("s5");
		Iterator<String> it = strs.iterator();
		while(it.hasNext()) {  //hasNext() 方法检查是否有下一个element
			String s = it.next();  // 游标移动到下一个element,并且将值赋给s
			if ("s3".equals(s)) {
				it.remove();    // 如果element是s3,删除该位置的element
			}
			
		}
			System.out.println(strs);
	}
}