Java集合之collection

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

 菜鸟教程:https://www.runoob.com/java/java8-streams.html

Java半颗糖
原文地址:https://www.cnblogs.com/2019wxw/p/11114289.html