java集合笔记

集合类相关知识

apache 常用工具类的使用

参考:https://juejin.im/post/5b1695595188257d37761e68

SynchronizedList 和 Vector 的区别

相同点

  1. 都是线程安全的
  2. 底层都是使用数组来实现的
    不同点(主要就是同步块和同步方法的区别)
  3. SynchronizedList有很好的扩展和兼容功能。他可以将所有的List的子类转成线程安全的类。
  4. 使用SynchronizedList的时候,进行遍历时要手动进行同步处理。
  5. SynchronizedList可以指定锁定的对象。

Enumeration 和 Iterator 区别

//Enumeration 源码
public interface Enumeration<E> {
    /**
     * 是否存在元素
     */
    boolean hasMoreElements();

    /**
     * 获取下一个元素
     */
    E nextElement();
}
// Iterator源码
public interface Iterator<E> {
    /**
     * 是否存在下一个元素
     */
    boolean hasNext();

    /**
     * 获取下一个元素
     */
    E next();

    /**
     * 删除元素
     */
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    /**
     * Performs the given action for each remaining element until all elements
     */
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

总结

  1. 方法数不同,Enumeration只有两个,Iterator有四个,Enumeration对操作对象是只读的,不支持其他操作,而Iteratior对操作对象可以执行移除操作
  2. Enumeration 是JDK 1.0添加的接口。使用到它的函数包括Vector、Hashtable等类,这些类都是JDK 1.0中加入的,Enumeration存在的目的就是为它们提供遍历接口。Enumeration本身并没有支持同步,而在Vector、Hashtable实现Enumeration时,添加了同步。
    而Iterator 是JDK 1.2才添加的接口,它也是为了HashMap、ArrayList等集合提供遍历接口。Iterator是支持fail-fast机制的:当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件

Collection 和 Collections 区别

  1. java.util.Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式
  2. java.util.Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。
    //常用Collections方法
    @Test
    public void testCollections(){
        List<Integer> list = Arrays.asList(1,3,2,5,9,8,6,5);
        //Collections.sort(list);//排序,out:1,2,3,5,5,6,8,9
        //int i = Collections.binarySearch(list, 5);//二分查找并范围匹配到第一个的索引,out:3
        //Collections.emptyList();//获取一个空list
        //Integer max = Collections.max(list);//获取当前集合中的最大值,out:9
        //System.out.println(max);
        Collections.rotate(list,4);//将当前集合从末尾开始截取指定长度的元素旋转到元素前面,out:[9, 8, 6, 5, 1, 3, 2, 5]
        System.out.println(list);
    }

fail-fast

fail-fast
介绍

java集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可鞥产生fail-fast事件。如:当A线程通过Iterator遍历集合时,若当前集合的内容被B线程所改变,那A线程访问集合时,就会剖出ConcurrentModificationException异常,产生fail-fast事件。注:只能用来检测错误,因为JDK并不保证fail-fast机制一定会发生

解决方法

使用Java.util.concurrent包下对应的类替换即可

示例及产生原理

示例

package test;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class TestFailFast  {
    //定义去全局变量
    private static List<String> list = new ArrayList<>();
    public static void main(String[] args) {
        //开启第一个线程,往集合中依次添加1,2,3,4,5,6
        new Thread(() -> {
            for(int i = 1;i <= 6;i++){
                list.add(i+"");
                foreachList();
            }
        }).start();
        //开启第二个线程,往集合中依次添加7,8,9,10,11
        new Thread(() -> {
            for(int i = 7;i <= 11;i++){
                list.add(i+"");
                foreachList();
            }
        }).start();
    }
    /**
     * 遍历集合
     */
    public static void foreachList(){
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            String str = iterator.next();
            System.out.println(str);
        }
    }
}
/** 输出结果,第一个线程在遍历过程中,第二个线程往集合中添加了一个元素,抛出异常
 * java.util.ConcurrentModificationException
 *	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
 *	at java.util.ArrayList$Itr.next(ArrayList.java:859)
 *	at test.TestString.foreachList(TestString.java:35)
 *	at test.TestString.lambda$main$1(TestString.java:23)
 *	at java.lang.Thread.run(Thread.java:748)
 */

产生原理
java8 ArrayList的Iterator 源码如下:

    private class Itr implements Iterator<E> {
        int cursor;       // 下一个元素的索引
        int lastRet = -1; // 最后一个元素的所有,如果没有则返回-1

        /**
        * 集合的每次增删改都会将modCount+1,每次创建Iterator是将modCount+1赋值给
        * expectedModCount,用来记录当前迭代集合的修改次数,在上面示例中,第一个线程向集合添加时遍历,
        * 获取迭代器的expectedModCount为6(假设),而第二个线程向集合中添加了一个元素,集合的modCount为6+1,
        * 所有迭代遍历调用next()方法中都会先调用checkForComodification();来判断expectedModCount与modCount是否相等,
        * 若不相等则抛出ConcurrentModificationException异常
        *
        */
        int expectedModCount = modCount; 

        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            //获取当前集合的元素
            Object[] elementData = ArrayList.this.elementData;
            /*若下一个元素索引 大于 当前元素集合大小时,同样说明有其他线程修改了当前集合,也会抛出ConcurrentModificationException异常*/
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);

                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        @Override
        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer<? super E> consumer) {
            Objects.requireNonNull(consumer);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i >= size) {
                return;
            }
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) {
                throw new ConcurrentModificationException();
            }
            while (i != size && modCount == expectedModCount) {
                consumer.accept((E) elementData[i++]);
            }
            // update once at end of iteration to reduce heap write traffic
            cursor = i;
            lastRet = i - 1;
            checkForComodification();
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

fail-safe

在对任何集合结构的修改都会在一个复制的集合上进行修改,因此不会抛出ConcurrentModificationException,但会产生大量的无效对象,开销大,且无法保证读取的数据与原始数据中的数据一致,如Java.util.concurrent包下与集合对应的操作类几乎都是fail-safe的

Java 8 中 stream 相关用法

分成stream(串行流) 和 parallelStream(并行流)

获取stream的方法

stream的静态方法

  • Stream.generate(() -> Arrays.asList(1,3,2,5,9,8,6,5))
  • Stream.of(1,2,3,4,5,6,6)
  • Stream.empty()
    可迭代对象的stream方法
  • Arrays.asList(1,3,2,5,9,8,6,5).stream()
基本用法
    @Test
    public void testStream(){
        List<Integer> list = Arrays.asList(1,3,2,5,9,8,6,5);
        //过滤出为偶数的元素并返回一个新的集合
        List<Integer> filterList = list.stream().filter(item -> item % 2 == 0).collect(Collectors.toList());//2,8,6

        //将list的每个元素都+1并返回新集合
        List<Integer> mapList = list.stream().map(item -> item + 1).collect(Collectors.toList());//2,4,3,6,10,9,7,6

        //打印集合的每个元素
        list.stream().forEach(System.out::println);//1,3,2,5,9,8,6,5

        //匹配当前列表的元素是否全为偶数,必须全部匹配时才返回true
        boolean b = list.stream().allMatch(item -> item % 2 == 0);//false

        //匹配当前列表的元素是否存在偶数,存在即返回true
        boolean b1 = list.stream().anyMatch(item -> item % 2 == 0);//true

        //获取当前流中的第一个元素,返回Optional
        Optional<Integer> first = list.stream().findFirst();
        first.get();//1

        //去除流中的重复元素
        List<Integer> distinctList = list.stream().distinct().collect(Collectors.toList());//1,3,2,5,9,8,6

        //获取流中元素为5的个数
        list.stream().filter(item -> item == 5).count();

        //类似于数据库中limit start , count
        list.stream().skip(1).limit(3);

        //执行reduction在此流中的元素,使用所提供的身份,积累和组合功能
        //第一个参数为上次执行的结果,item为当前元素值,返回值为Optional
        Optional<Integer> reduce = list.stream().reduce((sum, item) -> item + sum);
        System.out.println(reduce.get());
        //第一个参数为初始值,若stream为null,则返回指定值,不返回Optional ,因为不存在null
        Integer integer = list.stream().reduce(1, (sum, num) -> num + sum);
        System.out.println(integer);
        //第三个方法比第二个多了一个参数 BinaryOperator  combiner,这个是在并发执行的时候用的,用来把多个accumulator的结果结合到一起。
        Integer reduce1 = list.parallelStream().reduce(0, (sum, num) -> sum + num, (result1, result2) -> 
        result1 + result2);
        System.out.println(reduce1);
    }
collect用法
第一种用法
    /**
    * supplier 结果容器
    * accumulator 执行操作容器
    *   有两个参数 第一个参数:前一次的结果值
    *             第二个参数:当前计算数值
    * combiner: 合并策略 (只在并发情况下回调用)
    *             第一个参数:前一次结果值,
                  第二个参数:当前计算后的容器值
    *
    */      
    <R> R collect(Supplier<R> supplier,
                  BiConsumer<R, ? super T> accumulator,
                  BiConsumer<R, R> combiner);

    public void testCollect(){
        List<Integer> list = Arrays.asList(1,3,2,5,9,8,6,5);
        ArrayList<Object> collect = list.parallelStream().collect(ArrayList::new, (arrayList, el) -> {
            if(el % 2 != 0){
                arrayList.add(el);
            }
        }, (res1, res2) -> {
            res1.addAll(res2);
        });
        System.out.println(collect);//1,3,5,9,5
    }
第二种用法
    <R, A> R collect(Collector<? super T, A, R> collector);

class Person {
    private String name;
    private Integer age;
    private Integer height;

    public Person(String name, Integer age, Integer height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getHeight() {
        return height;
    }

    public void setHeight(Integer height) {
        this.height = height;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }
}

@Test
    public void testStream(){
        List<String> list = Arrays.asList("张三", "李四", "王五", "赵六");

        //Collectors.joining() 无缝拼接
        String s0 = list.stream().collect(Collectors.joining());
        System.out.println(s0);//张三李四王五赵六

        //Collectors.joining(参数为拼接时所用字符串)
        String s = list.stream().collect(Collectors.joining(","));
        System.out.println(s);//张三,李四,王五,赵六

        //Collectors.joining(拼接字符串,拼接前缀,拼接后缀)
        String s1 = list.stream().collect(Collectors.joining(",", "**", "&&"));
        System.out.println(s1);//**张三,李四,王五,赵六&&

        //Collectors.toList() 拼接成List集合 toSet()同理,知识转成Set类型
        List<String> toList = list.stream().collect(Collectors.toList());
        System.out.println(toList);//[张三, 李四, 王五, 赵六]

        //Collectors.counting() 获取收集到元素的个数
        Long len = list.stream().collect(Collectors.counting());
        System.out.println(len);//4


        //分组
        List<Person> personList = new ArrayList<>();
        Person person1 = new Person("张三",12,178);
        Person person2 = new Person("李四",15,168);
        Person person3 = new Person("王五",19,178);
        Person person4 = new Person("赵六",21,198);
        Person person5 = new Person("阿萨德",23,158);
        Person person6 = new Person("王宝强",35,170);
        Person person7 = new Person("假奶绿",30,165);
        personList.add(person1);
        personList.add(person2);
        personList.add(person3);
        personList.add(person4);
        personList.add(person5);
        personList.add(person6);
        personList.add(person7);


        //groupingBy(Function<? super T, ? extends K> classifier) 按指定key分组
        Map<String, List<String>> collect = list.stream().collect(Collectors.groupingBy(item -> item+"1"));
        System.out.println(collect);//{王五1=[王五], 赵六1=[赵六], 张三1=[张三], 李四1=[李四]}

        //将年龄作为key,值为每个person
        Map<Integer, List<Person>> collect1 = personList.stream().collect(Collectors.groupingBy(item -> item.getAge()));
        System.out.println(collect1);//{35=[Person{name='王宝强', age=35, height=170}], 19=[Person{name='王五', age=19, height=178}], 21=[Person{name='赵六', age=21, height=198}], 23=[Person{name='阿萨德', age=23, height=158}], 12=[Person{name='张三', age=12, height=178}], 30=[Person{name='假奶绿', age=30, height=165}], 15=[Person{name='李四', age=15, height=168}]}

        //将name作为key,并将值封装到set集合
        Map<String, Set<Person>> setMap = personList.stream().collect(Collectors.groupingBy(item -> item.getName(), Collectors.toSet()));
        System.out.println(setMap);//{李四=[Person{name='李四', age=15, height=168}], 张三=[Person{name='张三', age=12, height=178}], 王宝强=[Person{name='王宝强', age=35, height=170}], 王五=[Person{name='王五', age=19, height=178}], 假奶绿=[Person{name='假奶绿', age=30, height=165}], 赵六=[Person{name='赵六', age=21, height=198}], 阿萨德=[Person{name='阿萨德', age=23, height=158}]}

        //指定key-value上限类型,将name作为key,并将值封装到Map集合
        HashMap<String, Map<Integer, Integer>> collect2 = personList.stream().collect(Collectors.groupingBy(Person::getName, HashMap::new, Collectors.toMap(Person::getAge, Person::getHeight)));
        System.out.println(collect2);//{李四={15=168}, 张三={12=178}, 王宝强={35=170}, 王五={19=178}, 假奶绿={30=165}, 赵六={21=198}, 阿萨德={23=158}}

    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园建设方案旨在通过融合先进技术,如物联网、大数据、人工智能等,实现校园的智能化管理与服务。政策的推动和技术的成熟为智慧校园的发展提供了基础。该方案强调了数据的重要性,提出通过数据的整合、开放和共享,构建产学研资用联动的服务体系,以促进校园的精细化治理。 智慧校园的核心建设任务包括数据标准体系和应用标准体系的建设,以及信息化安全与等级保护的实施。方案提出了一站式服务大厅和移动校园的概念,通过整合校内外资源,实现资源共享平台和产教融合就业平台的建设。此外,校园大脑的构建是实现智慧校园的关键,它涉及到数据中心化、数据资产化和数据业务化,以数据驱动业务自动化和智能化。 技术应用方面,方案提出了物联网平台、5G网络、人工智能平台等新技术的融合应用,以打造多场景融合的智慧校园大脑。这包括智慧教室、智慧实验室、智慧图书馆、智慧党建等多领域的智能化应用,旨在提升教学、科研、管理和服务的效率和质量。 在实施层面,智慧校园建设需要统筹规划和分步实施,确保项目的可行性和有效性。方案提出了主题梳理、场景梳理和数据梳理的方法,以及现有技术支持和项目分级的考虑,以指导智慧校园的建设。 最后,智慧校园建设的成功依赖于开放、协同和融合的组织建设。通过战略咨询、分步实施、生态建设和短板补充,可以构建符合学校特色的生态链,实现智慧校园的长远发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值