廖雪峰java教程学习笔记——集合

Java的java.util包主要提供了三种类型的集合:List、Set、Map

Java集合的设计特点:

  1. 接口和实现类相分离,例如有序表的接口是List,具体的实现类有ArrayList、LinkedList等
  2. 支持泛型
  3. 访问集合总是通过迭代器

注意:避免使用历史遗留类和接口

有一小部分集合类是遗留类,不应该继续使用:

  1. Hashtable:一种线程安全的Map实现;
  2. Vector:一种线程安全的List实现;
  3. Stack:基于Vector实现的LIFO的栈。

还有一小部分接口是遗留接口,也不应该继续使用:

  1. Enumeration:已被Iterator取代。

List 有序列表

List<E>接口主要有以下方法:

在末尾添加一个元素:boolean add(E e)
在指定索引添加一个元素:boolean add(int index, E e)
删除指定索引的元素:E remove(int index)
删除某个元素:boolean remove(Object e)
获取指定索引的元素:E get(int index)
获取链表大小(包含元素的个数):int size()

常用的实现有:ArrayList和LinkedList

ArrayList

ArrayList内部由数组实现,增删元素时会自动将其余元素挪位置,加满时会自动创建一个更大的数组,将原数组的所有元素复制过去,取代旧数组。

LinkedList

LinkedList内部由链表实现。

创建List

方法一:创建空List,用add添加元素
        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(3);

或用双括号:

List<Integer> list=new ArrayList<Integer>(){
   {
   
                        add(1);
                        add(2);
                        add(3);
                          }};
方法二:使用Arrays.asList()
//创建List
List<Integer> list=Arrays.asList(1, 2, 3);  //注意要用Integer
//创建元素为List的list
List<List<Integer>> list = Arrays.asList(Arrays.asList(1,2), Arrays.asList(3,4));

注意Arrays.asList()创建的List是一个只读对象,不能再用add操作了:

        List<Integer> list = List.of(12, 34, 56);
        list.add(999); // UnsupportedOperationException

asList 是 java.util.Arrays 类的一个方法

public static <T> List<T> asList(T... a) {
   
        return new ArrayList<>(a);
}

容易犯的错误:

        int[] array = {
   1,2,3};
        List myList = Arrays.asList(array);  //将array对象作为list元素了

因为asList的接口是泛型:List<T> asList(T...) ,int作为原始类型不属于Object,所以不能被作为泛类型参数。整个数组倒是一个Object,所以整个数组就用来取代T,所以得到了一个List<int[]>。正确的做法是传入一个Integer[],就能得到一个List<Integer>了。

方法三:从Stream中创建
@Test
public void givenStream_thenInitializeList(){
   
    List<String> list = Stream.of("foo", "bar")
      .collect(Collectors.toList());
		
    assertTrue(list.contains("foo"));
}
方法四:工厂方法 .of (Java 9)

Java 9+ 版本,可以用List.of()取代Arrays.asList()

遍历List

方法一:for循环 + get(i)
        for (int i=0; i<list.size(); i++) {
   
            String s = list.get(i);
            System.out.println(s);
        }

不推荐这种方法,因为只对ArrayList高效,对LinkedList很低效。

方法二:迭代器Iterator (推荐!)

迭代器:

        for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
   
            String s = it.next();
            System.out.println(s);
        }

简化版为:

		//自动使用迭代器
        for (String s : list) {
   
            System.out.println(s);
        }

不同的List类型,返回的Iterator对象实现也是不同的,但总是具有最高的访问效率。

Java的for each循环会自动使用Iterator遍历。实际上,只要实现了Iterable接口的集合类都可以直接用for each循环来遍历。

List转为Array

Integer[] array = list.toArray(new Integer[3]);
Integer[] array = list.toArray(new Integer[list.size()]);
Integer[] array = list.toArray(Integer[]::new);  //函数式写法

编写equals方法

List中contains()、indexOf()等方法使用equals()方法判断两个元素是否相等。

因此,对于自定义的类型,要想正确使用List的contains()、indexOf()这些方法,放入的实例必须正确覆写equals()方法,否则,放进去的实例查找不到。

public class Person {
   
    public String name;
    public int age;
}

public boolean equals(Object o) {
   
    if (o instanceof Person) {
   
        Person p = (Person) o;
        //引用字段用equals,基本类型字段用==
        return this.name.equals(p.name) && this.age == p.age;
    }
    return false;
}

但上面方法中若this.namenullequals()方法就会报错。一种解决方式是手动判断是否为null,但这显然太麻烦。一般使用Objects.equals()静态方法即可。

标准覆写equals()方法样例:

public boolean equals(Object o) {
   
    if (o instanceof Person) {
   
        Person p = (Person) o;  //安全向下转型
        return Objects.equals(this.name, p.name) && this.age == p.age;
    }
    return false;
}

Map 映射表

put(),get()分别用于添加、获取映射。

        Student s = new Student("Xiao Ming", 99);
        Map<String, Student> map = new HashMap<>();  //创建HashMap
        map.put("Xiao Ming", s); // 添加元素
        Student target = map.get("Xiao Ming"); // 查找元素

遍历Map,顺序是不确定的:

        //方法一:通过key遍历,keySet()相当于python中的keys()
        for (String key : map.keySet()) {
     
            Integer value = map.get(key);
            System.out.println(key + " = " + value);
        }
		//方法二:直接遍历key、value,entrySet()相当于python中的items()
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
   
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + " = " + value);
        }

用List存储全量数据,用Map做缓存的例子:

class Students {
   
	List<Student> list;//定义了一个Student的List,可能十分巨大
	Map<String, Integer> cache;//定义了一个Map,缓存
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值