Java:集合:List / Map / for循环 / steam

更多
2021年08月31日 15点54分 作者:叶飞 修改

复习:J&C:集合概述 / 迭代器模式

Java中所有常用集合都在java.util包下,所以可以

import java.util.*;


List

Java中List本身是一个泛型接口,继承自Collection,最常用的实现类是ArrayList。

演示:

  • 除ArrayList以外,还有LinkedList、vector下的Stack
  • List中定义的方法:get()/set()/add()/remove()/indexOf()……

ArrayList

千万要忘了初始化!

ArrayList<Integer> scores = null;
//不会是false,而是报错:NullPointerException
System.out.println(scores.isEmpty()); 

其他增删改查方法:

ArrayList<Integer> scores = new ArrayList<>();
System.out.println(scores.size()); 

scores.add(12);   //按下标index依次添加的
scores.add(25);
scores.set(0, 21);   //只能改,不能加
System.out.println(scores.isEmpty());
System.out.println(scores.size());    //存放元素个数:2 System.out.println(scores.get(0));
System.out.println(scores.get(1));

System.out.println(scores.contains(21));    //true
System.out.println(scores.contains(28));    //false

System.out.println(scores.indexOf(21));   //返回下标:0
System.out.println(scores.indexOf(28));   //找不到:-1

scores.remove(0);    //删除下标为0的元素
scores.remove(12);    //删除元素12
scores.clear();    //清除所有元素 

size和capacity

为什么要使用集合?数组不够强大,^_^

比如:数组能不能add()?

但为什么ArrayList就能一直add()呢?其实现原理和StringBuilder非常类似:

  1. ArrayList内部维护着一个数组elementData,所有数据实际上装在这里面
  2. 数组有一个初始长度:DEFAULT_CAPACITY = 10,也可以在初始化时指定capacity,代替默认的
    public ArrayList(int initialCapacity) {
  3. 每次add()的时候检查数组长度是否足够,不够的话,自动扩容

源代码演示内部实现:扩容的方法

    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;    //elementData:数组容器
        int newCapacity = oldCapacity + (oldCapacity >> 1);

PS:位运算右移(>>)各二进位全部右移若干位,相当于乘以2(但建议我们的代码也这么写:降低可读性)

@想一想@:既然ArrayList这么强大,还有必要使用数组么?

foreach

因为所有集合都采用迭代器模式,实现了iterable,所以可以用一种统一的模式来遍历集合元素。

Java干脆更进一步,在语法层面提供了foreach迭代:

List<Person> people = new ArrayList<>();
for (Person person : people) {
	System.out.println(person.Name);
}

@想一想@:能不能使用for循环么?

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

能。但是:

  • foreach基于iterable,所有集合都可以使用
  • for基于index,只有List才能使用


Set

Set和List非常类似,都继承自Collection,所以有相同的增(add)删(remove/clear)查(isEmpty/contains)方法。

Set是一个接口,常用的实现类是HashSet和TreeSet(演示)

但是,因为Set不允许重复,所以重复的元素会被自动合并:

Set<Person> people = new HashSet<>();

Person atai = new Person();
people.add(atai);
people.add(atai);
people.add(atai);

System.out.println(people.size());   //始终是1

@想一想@:抛异常是不是更好一些?所以推荐这种写法:

if (!people.contains(atai)) {    //增加代码可读性
	people.add(atai);	
}

此外,因为Set没有索引,所以不能精确查找某个元素,当然也不能更改。一个变通的方法是:先删除,再添加。

//先删除后添加 = 更改
people.remove(atai);
Person bo = new Person();
bo.Name = "波仔";
people.add(bo);
最后,Set可以foreach遍历,没法for循环:
for (Person person : people) {
	System.out.println(person.Name);
}


Map

继承结构

Java中Map本身是一个泛型接口,常用的实现类有:HashMap和HashTable。

#常见面试题:两者的区别?#

主要是在线程安全(后文详述)方面:

  • HashMap:适合于单线程,非线程安全
  • Hashtable:适合于多线程,线程安全

因为HashMap更新(内部实现了Tree),一般情况推荐使用HashMap,多线程时推荐ConcurrentHashMap。

常用方法

scores.put("atai", 100.0);    //增
scores.remove("atai");    //删:通过key
scores.replace("atai", 98.5);     //改
//查
System.out.println(scores.get("atai"));
System.out.println(scores.getOrDefault("atai", 80.0));    //查不到给默认值
System.out.println(scores.containsKey("atai"));     //检查“键”
System.out.println(scores.containsValue(100.0));    //检查“值”

注意:Map的key也是不允许重复的,如果put时有重复,和Set一样处理。不报错,后面的键值对覆盖前面的。

没有foreach

因为Map没有继承自iterable,所以是能直接foreach遍历的!

如果确实要遍历,需要首先进行转化,拿到

  • 所有的键(key):
    for (String student : scores.keySet()) {
  • 所有的值(value):
    for (Double score : scores.values()) {
  • 所有的键值对(entry)
    for (Map.Entry<String, Double> entry : scores.entrySet()) {
    	System.out.println(
    			entry.getKey() +   //键
    			":" + 
    			entry.getValue()); //值
    }
    注意Entry是Map的内部接口,所以只能通过Map点出。
    另:entry还有一个setValue()方法,可以更改它的值。


作业

  1. 在现有作业的基础上,观察一起帮文章板块,以此为蓝本,补充(如果还没有的话)声明:
    • 评论(Comment)类
    • 评价(Appraise)类:包括“赞(Agree)”和“踩(Disagree)”
    • 关键字(Keyword)类
    并构建以下关系:
    • 一篇文章可以有多个评论
    • 一个评论必须有一个它所评论的文章
    • 每个文章和评论都有一个评价
    • 一篇文章可以有多个关键字,一个关键字可以对应多篇文章
  2. 构建一个
  3. 让之前的双向链表,能够:被foreach迭代

Java 集合
赞: 0 踩: 0

打赏
已收到打赏的 帮帮币

你的 打赏 非常重要!
为了保证文章的质量,每一篇文章的发布,都已经消耗了作者 1 枚 帮帮币
没有“帮帮币”,作者无法发布新的文章。

全系列阅读
评论 / 0

后台开发


其他:WebForm和WebApi

其他ASP.NET框架,如WebForm、WebApi……

RazorPages(Core)

微软推荐的、最新的、基于Razor页面和.NET core的新一代Web项目开发技术,包括Razor Tag Helper、Model绑定和Validation、Session/Cookie、内置依赖注入等……

MVC(Framework)

过去两年间最流行的、基于.NET Framework和MVC模式的ASP.NET MVC框架,主要用于讲解安全、性能、架构和各种实战功能演示……

C#语法

从入门的变量赋值、分支循环、到面向对象,以及更先进的语言特性,如:泛型、Lambda、Linq、异步方法等…………

Java语法

面向过程的变量赋值、分支循环和函数封装;面向对象的封装、继承和多态;以及更高阶的常用类库(集合/IO/多线程……)、lambda等

Java Web开发

SpringMVC

分层架构和综合实战

J&C

Java和C#共有的语法

全部
关键字



帮助

反馈