Java集合框架系统学习4 - List接口常用方法

本章介绍List接口的一些常用方法是什么功能。因为List继承了Collection接口,所以从这个接口里继承而来的方法就不介绍了。
详见Collection接口方法:https://blog.csdn.net/qq_31618549/article/details/121758434

default void replaceAll(UnaryOperator<E> operator) {
    Objects.requireNonNull(operator);
    final ListIterator<E> li = this.listIterator();
    while (li.hasNext()) {
        li.set(operator.apply(li.next()));
    }
}

这个方法用来对列表进行一个一一映射,我们需要传入UnaryOperator的实现类,来规定映射规则。比如我要将列表中的数字变为原来的两倍。就可以这么做:

public class Main
{
    public static void main(String[] args)
    {
        List<Integer> list=new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.replaceAll(new UnaryOperator<Integer>() {
            @Override
            public Integer apply(Integer integer) {
                return integer*2;
            }
        });
        System.out.println(list);
    }
}

输出是:

[2, 4, 6]

跟我们预想的一致。

2、

default void sort(Comparator<? super E> c) {
    Object[] a = this.toArray();
    Arrays.sort(a, (Comparator) c);
    ListIterator<E> i = this.listIterator();
    for (Object e : a) {
        i.next();
        i.set((E) e);
    }
}

sort方法用来对列表进行排序,排序的规则需要我们自己定义,也就是实现这个Comparator<? super E>接口。
比如我有一个电脑类:

public class Computer
{
    public String name;
    public int price;
    public int memorySize;
    
    public Computer(String name, int price, int memorySize) 
    {
	    this.name = name;
	    this.price = price;
	    this.memorySize = memorySize;
	}
    @Override
    public String toString() {
        return "Computer{" +
                "name='" + name + '\'' +
                ", price=" + price +
                ", memorySize=" + memorySize +
                '}';
    }
}

接下来我通过一个列表对象,将电脑对象存储起来,之后调用这个列表类的sort对象,传入一个比较规则(规定如果前者小于后者返回-1,等于返回0,大于返回1,注意这是java规定的,不是我规定的)。这里我们就按照价格从小到大的顺序来排序:

package list;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.UnaryOperator;

public class Main
{
    public static void main(String[] args)
    {
        List<Computer> computers=new ArrayList<>();
        computers.add(new Computer("联想510S",5000,4*1024*1024));
        computers.add(new Computer("戴尔7080MT",9000,16*1024*1024));
        computers.add(new Computer("惠普暗影精灵6",8699,8*1024*1024));
        computers.sort(new Comparator<Computer>() {
            @Override
            public int compare(Computer o1, Computer o2) {
                if(o1.price<o2.price)
                {
                    return -1;
                }
                if(o1.price==o2.price)
                {
                    return 0;
                }
                return 1;
            }
        });
        System.out.println(computers);
    }
}

输出:

[Computer{name='联想510S', price=5000, memorySize=4194304}, Computer{name='惠普暗影精灵6', price=8699, memorySize=8388608}, Computer{name='戴尔7080MT', price=9000, memorySize=16777216}]

符合我们的预期。

3、

E get(int index);

这个很简单,返回下标为index的元素。

4、

E set(int index, E element);

将指定下标的元素替换为目标元素,简单给个代码:

public static void main(String[] args)
{
	List<String> list=new ArrayList<>();
	list.add("1");
	list.add("2");
	list.add("3");
	list.set(1,"9");
	System.out.println(list);
}

输出为:

[1, 9, 3]

5、

void add(int index, E element);

在指定下标处添加元素,如果该下标已有元素,那么该元素及该元素后面的所有元素都会顺位往后移动一位,来给新元素腾出位置。

6、

E remove(int index);

删除指定下标的元素

7、

int indexOf(Object o);

返回o在列表中的下标(如果列表有多个一样的元素,则返回最小的那个下标)

8、

int lastIndexOf(Object o);

跟上面一样,这个是返回最大的下标。

9、

ListIterator<E> listIterator();

List接口为我们提供了一个新的迭代器,当然我们依然可以使用Collection接口中自带的Iterator迭代器。
listIterator迭代器继承自Iterator。在Iterator的基础上拓展了一些功能。
有了listIterator后,我们可以双向遍历元素(Iterator是单向的),以及能够在遍历的同时对列表里的元素进行增添操作。
双向遍历很好理解,单向遍历为我们提供了hasNext和next方法,供我们向后遍历。那么双向遍历在此基础上为我们增加了一对方法,分别是hasPrevious和previous,供我们向前遍历。
如果看源码,我们会发现listIterator里面有remove和add方法,这个其实就对应着之前说的“能够在遍历的同时对列表里的元素进行增添操作”。可能有的人不明白为什么要提供这两个方法,list接口里不是已经有get和set方法了吗。其实并没有多此一举。如果我们在遍历的时候调用了list里面的get和set方法,就会报一个ConcurrentModificationException异常,这个异常就是为了提醒程序员要注意遍历的同时对列表进行增删容易出现问题,会使得遍历结果很乱,即使有时候它确实不会出问题。那为什么调用listIterator自带的remove和add方法就不会出问题呢,因为调用listIterator自带的remove和add方法时方法内部在进行增删操作后会进行一步更新listIterator内部成员变量的操作(比如cursor变量),让它指向一个合理正确的位置,这样子迭代器就不会出现乱七八糟的遍历结果。
注意以上都是建立在单线程前提下讨论的,如果是多线程,并且这个list本身线程不安全,那么即使我们用的是迭代器内部的remove和add操作,也会出现异常报错。

10、

ListIterator<E> listIterator(int index);

和9差不多,没啥好说的,就是返回头从index开始的迭代器。9那个就可以理解为头从0开始的迭代器。

11、
List subList(int fromIndex, int toIndex);
返回一个子列表,区间为[fromIndex,toIndex)
注意这个子列表里的元素还是原来列表里的元素,所以我们对这个子列表的元素进行操作时,原列表里对应的那个元素也会发生变化。

12、

static <E> List<E> of(E... elements)

这个是一个静态方法,用来快速生成一个新列表,比如:

List<String> list=List.of("1","2","3","4","5","1","2","3","4","5","7","9")

不过这个方法返回的对象实例是NList类型的,这个类型不允许修改列表元素。否则会报UnsupportedOperationException异常。总之我没用过这个方法,我也是看了源码才知道。具体有什么用不做探讨。

13、

static <E> List<E> copyOf(Collection<? extends E> coll) {
        return ImmutableCollections.listCopy(coll);
    }

利用已有的集合,copy一份新的列表。注意,新列表的对象和原来集合中的对象是同一份,所以不能当作一份独立的新列表来操作。

就介绍到这了,我已经把源码里有的都列出来了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值