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 void main(String[] args) { 2 Collection c=new ArrayList(); 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=new HashSet(); 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 void main(String[] args) { 2 Collection c=new ArrayList(); 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=new HashSet(); 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=new HashSet(); 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=new HashSet(); 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<Integer> transactionsIds = lists.stream() .filter(b -> b.getColor() == RED) .sorted((x,y) -> x.getWeight() - y.getWeight()) .mapToInt(Widget::getWeight) .sum();
1,什么是流,
Stream(流)是一个来自数据源的元素队列并支持聚合操作
- <strong元素队列< strong="">元素是特定类型的对象,形成一个队列。 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)实现。
参考文档:https://blog.csdn.net/IO_Field/article/details/54971761