重学Java之List
0、概述
一个Java对象可以在内部持有若干其他Java対象,并对外提供访问接口,这种Java对象称为集合。
- Java的数组可以看作是一种集合
有了数组为什么还需要其他集合类?
- 数组初始化后大小不可变
- 数组只能按索引顺序存取
java.util提供了集合类,包括:
Collection:集合类的根接口
- List:有序列表
- Set:无重复元素集合
Map:通过Key查找Value的映射表
Java集合设计的特点:
-
接口和实现相分离:
List接口: ArrayList, LinkedList
-
支持泛型:
List list = new ArrayList<>();
-
访问集合有统一的方法:
迭代器(Iterator)
总结
- Java集合类定义在java.util包中
- 常用的集合类包括List, Set, Map等
- Java集合使用统一的Iterator遍历集合
- 尽量不要使用遗留接口
一、List
概述
List是一种有序链表
- List内部按照放入元素的先后顺序存放
- 每个元素都可以通过索引确定自己的位置
- 类似数组,但大小可变
- List的元素可以重复
- List的元素可以是null
常用方法
- void add(E e)在末尾添加一个元素
- void add(int index, E e)在指定索引添加一个元素
- int remove(int index)删除指定索引的元素
- int remove(Object e)删除某个元素
- E get(int index)获取指定索引的元素
- int size()获取链表大小(包含元素的个数)
- List内部按照放入元素的先后顺序存放
- 每个元素都可以通过索引确定自己的位置
- boolean contains(Object o)是否包含某个元素
- int indexOf(Object o)查找某个元素的索引,不存在返回-1
ArrayList & LinkedList
数组也是有序结构,但是大小固定,且删除元素时需要移动后续元素。
ArrayList:内部使用数组存储所有元素
LinkedList:内部每个元素都指向下一个元素
遍历
使用get(int index)
// ArrayList效率高一点
List<String> list = ...
for (int i=0; i<list.size(); i++){
String s = list.get(i);
}
使用Iterator
List<String> list = ...
for (Iterator<String> it = list.iterator();
it.hasNext();) {
String s = it.next() ;
}
使用foreach
所有实现了Iterable借口的类都可以使用foreach循环遍历
List<String> list = ...
for (String s : list){
}
List和Array转换
把List变为Array
- Object[] toArray()
- T[] toArray(T[] a)
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Integer[] array = list.toArray (new Integer [3]);
// Integer[] [ 1, 2, 3 ]
Integer[] array = list.toArray (new Integer [2]);
//{1,2,3}
Integer[] array2 = list.toArray (new Integer[5]);
//{1, 2,3, null, null}
Integer[] array3 = list.toArray (new Integer[list.size]);
//
把Array变为List
- List Arrays.asList(T… a)
Integer[] array = {1,2,3};
List<Integer> list = Arrays.asList(array);
//注意返回的1ist并不是ArrayList,并且是只读的
list.add(4) ; // UnsupportedOperationException !
//把Array转变为ArrayList<E>
List<Integer> list = Arrays.asList (array) ;
List<Integer> arrayList = new ArrayList<> ();
arrayList.addAll(list) ;
List<Integer> arrayList =new ArrayList<> (Arrays.asList(array)) ;
例子
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Pear");
list.add("Orange");
for (String s : list) {
System.out.println(s);
}
}
}
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Pear");
list.add("Orange");
String[] ss = list.toArray(new String[list.size()];
for (String s : ss) {
System.out.println(s);
}
编写equals方法
boolean contains(Object o)的方法实现的原理是equals。
返回的是false,原因是Person类中的equals方法是用==来实现的。
这里尝试编写编写equals方法复写Person类中的equals方法。
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
list.add(new Person("Ming", 12));
list.add(new Person("Hong", 15));
list.add(new Person("Jun", 18));
System.out.println(list);
System.out.println(list.contains(new Person("Jun", 18)));
}
}
public class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "(Person: " + name + ", " + age + ")";
}
public boolean equals(Object o){
if(this == o){
return true;
}
if(o instanceof Person){
Person p = (Person)o;
//return (p.name == this.name || p.name != null && p.name.equals(this.name)) && p.age == this.age ;
return Objects.equals(p.name,this.name) && p.age == this.age;
}
}
}
总结
- 按索引顺序访问的长度可变的链表
- 优先使用ArrayList而不是LinkedList
- 可以直接使用for…each遍历
- 可以和Array相互转换
如果要在List中查找元素:
- List的实现类通过元素的equals方法比较两个元素
- 放入的元素必须正确覆写equals方法
JDK提供的String、Integer等已经覆写了equals方法
- 编写equals方法可借助Objects. equals()判断
如果不在List中查找元素:
- 不必覆写equals方法