1,java集合的定义
Java集合是一种有序的工具类,可用于存储数量不等的对象,并可以实现常用的数据结构,如,栈,队列等。
历史介绍:Java 就像是一种容器,可以把多个对象(实际是对象的引用,习惯上称为对象),放进该容器中。
Jdk 1.5之前,java集合会丢失容器中所有对象的数据类型,把所有对象都当成Object类型处理。
jdk 1. 5之后,增加了泛型,java集合可以记住容器中的数据类型,从而可以编写出更简洁健壮的代码。
2,java集合与数组的关系
1,数组长度在初始化时指定,意味着只能保存定长的数组;而集合可以保存数量不确定的数据,同时可以保存具有映射关系的数据(关联数组 key-->value)
2,数组元素既可以是基本数据类型的值,也可以是对象,集合里只能保存对象(实际上是对象的引用变量)基本类型的对象要转化成包装类才能放入集合。
3,Java集合之间的继承关系
Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口。
(1)ArrayList,HashSet,LinkedList,TreeSet是我们经常会有用到的已实现的集合类。
(2)Map实现类用于保存具有映射关系的数据。Map保存的每项数据都是key-value对,也就是由key和value两个值组成。
Map里的key是不可重复的,key用户标识集合里的每项数据。HashMap,TreeMap是我们经常会用到的集合类。
总结:1,访问List可以根据元素的索引来访问,
2,访问map可以根据可以根据每项元素的key来访问Value;
3,访问Set可以根据元素本身来访问(这也是set集合元素不能重复的原因)
4,Collection 接口是Set,List,Queue接口的父接口,该接口定义的方法可以也可用于操做子接口集合。比如:
(1)Collection集合的使用实例:
1 public static voidmain(String[] args) {2 Collection c=newArrayList();3 //添加元素
4 c.add("孙悟空");5 //虽然集合里不能放基本类型的数剧,但是jdk支持自动装箱
6 c.add(8);7 System.out.println("c集合大小:"+c.size());8 //删除指定元素
9 c.remove(8);10 System.out.println("c集合大小:"+c.size());11 //判断集合是否包含指定字符串
12 System.out.println("判断集合是否包含字符串:"+c.contains("孙悟空"));13 c.add("轻量级JavaE");14 System.out.println("c集合:"+c);15 //测试是否包含指定集合 新建一个集合
16 Collection books=newHashSet();17 books.add("轻量级JavaE");18 books.add("疯狂Java讲义");19 System.out.println("是否完全包含指定集合:"+c.containsAll(books));20 //用c结合减去books集合里有的元素 去重
21 c.removeAll(books);22 System.out.println("c集合减去books中的元素:"+c);23 c.clear();24 System.out.println("删除所有元素:"+c);25 c.add("轻量级JavaE");26 books.retainAll(c);//提取公共部分27 System.out.println("控制books集合只包含c集合中有的元素:"+books);28 }
运行效果:
(2)Lambda表达式遍历集合
1 public static voidmain(String[] args) {2 Collection c=newArrayList();3 c.add("Java疯狂讲义0");4 c.add("Java疯狂讲义1");5 c.add("Java疯狂讲义2");6 c.add("Java疯狂讲义3");7 System.out.println("使用Lambda遍历集合:");8 c.forEach(data->System.out.println(data));9 }
运行结果:
(3)使用Java jdk1.8增强的Iterator遍历集合元素(Iterator对象也被称为迭代器)
Iterator接口经常被称作迭代器,它是Collection接口的父接口。但Iterator主要用于遍历集合中的元素。
Iterator接口中主要定义了4个方法:
1 //Iterator迭代集合
2 Collection books=newHashSet();3 for(int i =0;i<4;i++){4 books.add("java疯狂"+i);5 }6 //获取books的迭代器
7 Iterator it=books.iterator();8 while(it.hasNext()){9 //it.next()方法返回数据类型为Object类型,需要强制转换
10 String b=(String)it.next();11 System.out.println(b);12 if(b.equals("java疯狂1")){13 //从集合中删除上一次返回的元素
14 it.remove();15 }16 //对b变量赋值,不会改变集合本身
17 b="测试数据";18 }19 System.out.println(books);
运行效果:
总结:Iterator仅用于遍历集合,Iter本身并不盛装对象的能力,如果需要创建Iterator对象,则必须有一个被迭代的集合,没有集合的Iterator仿佛无本之木,没有存在的价值。
注意:当使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素本身传给了迭代变量,而是把集合元素的值传给了迭代变量(就如同参数传递是值传递,基本数据类型传递的是值,
引用类型传递的仅仅是对象的引用变量),所以修改迭代变量的值对集合元素本身没有任何影响。
在Iterator迭代块内,也就是在Iterator迭代Collection集合过程中修改Collection集合,应发异常。
1 //获取books的迭代器
2 Iterator it=books.iterator();3 while(it.hasNext()){4 //it.next()方法返回数据类型为Object类型,需要强制转换
5 String b=(String)it.next();6 System.out.println(b);7 if(b.equals("java疯狂1")){8 //使用Iterator迭代过程中,不可修改集合元素,下面代码发生异常
9 books.remove(b);10 }11 }12 System.out.println(books);
运行效果:
Iterator采用的是快速失败fail-fast机制,一旦检测到该集合已经被修改(通常是程序中其他线程修改),程序立即引发ConcurrentModificationException异常,而不是显示修改后的结果,
这样可以避免共享资源而引发的潜在问题。
(4)lambda表达式遍历Iterator
jdk 1.8的Iterator新增了forEachRemaining(Consumer action) 方法,该方法所需的参数同样也是函数式接口,当程序调用Iterator的forEachRemaining()方法
遍历集合元素时,程序会依次将集合元素传给Consumer的accept( T t)方法(接口中唯一的抽象方法)
//Iterator迭代集合
Collection books=newHashSet();for(int i =0;i<4;i++){
books.add("java疯狂"+i);
}//使用lambda表达式遍历集合元素
Iterator it=books.iterator();
it.forEachRemaining(book-> System.out.println("迭代集合元素:"+book));
运行结果:
(5)使用forEach循环遍历集合元素;
除了使用Iterator接口迭代访问Collection集合外,还可以使用java5提供的forEach循环迭代访问集合元素更加便捷,
1 Collection books=newHashSet();2 for(int i =0;i<4;i++){3 books.add("java疯狂"+i);4 }5 //使用forEach遍历集合元素
6 for(Object obj:books) {7 //此处book变量也不是集合元素本身,只是一个引用
8 String book=(String)obj;9 System.out.println(book);10 }
运行结果:
(5)Java的Stream操作集合
继Java 8系列之Lambda表达式之后,我们来了解Stream。Stream 是用函数式编程方式在集合类上进行复杂操作的工具,
其集成了Java 8中的众多新特性之一的聚合操作,开发者可以更容易地使用Lambda表达式,并且更方便地实现对集合的查找、遍历、过滤以及常见计算等。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
+--------------------+-----------------------+------++------++---++-------+
|stream of elements +----->|filter+->|sorted+->|map+->|collect|
+--------------------++------++------++---++-------+
以上流程转换为Java代码:
List transactionsIds =lists.stream()
.filter(b-> b.getColor() ==RED)
.sorted((x,y)-> x.getWeight() -y.getWeight())
.mapToInt(Widget::getWeight)
.sum();
1,什么是流,
Stream(流)是一个来自数据源的元素队列并支持聚合操作
元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:
Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。