java SE--集合

1.Collection接口

Collection接口是List,Set,Queue接口的父接口,里面提供了子类的常用方法;

List储存的是可以重复的,有序的数据,子类是arrayList(数组结构)和linkedList(双向链表)

我们主要研究一下Collection接口中封装的方法

//使用多态的向上造型创建一个子类型对象
        Collection<String> c1 = new ArrayList<>();
        //1.E add(E e)  向集合中添加元素
        c1.add("A");
        c1.add("B");
        c1.add("C");
        //2.Boolean isEmpty()
        boolean b1 = c1.isEmpty();
        System.out.println(b1);

首先利用多态的向上造型创建一个子类型对象c1,并向集合中添加元素,利用对象.add( )的方法,该类型的返回值是泛型变量;

之后判断一个集合是否为空,返回值是一个boolean类型的变量;同样是使用对象名.isEmpty()的方法

 //3.int size()  返回的是集合元素的个数
        System.out.println(c1.size());

        //4.String toString()   将集合转换为字符串形式
        System.out.println(c1.toString());

        Collection<String> c2 = new ArrayList<>();
        c2.add("B");
        c2.add("C");
        c2.add("D");
        //5. addAll(Collection c)
        c1.addAll(c2);
        System.out.println(c1);

想要返回集合中元素的个数,需要调用方法对象名.size( ),该方法的返回值是一个int类型的变量;如果需要将集合转换为字符串形式,需要调用对象名.toString( ),该方法的返回值是String类型;如果想将B集合的所有元素添加到A集合中,需要调用方法 A.addAll(B);该方法的返回值是对象的类型

//6.boolean contains(Object o)
        //查看是否包含字符串B
        boolean contains = c1.contains("B");
        System.out.println("contains: "+contains);

        //7.boolean  containsAll(Collection c)
        boolean containsAll = c1.containsAll(c2);
        System.out.println("c1是否包含集合c2: "+containsAll);

        //8.boolean  equals(Object o)
        //测试:  创建一个新的集合c3,添加元素“A” "B" "C" "B" "D" "D"  判断两个集合是否相等
        Collection<String> c3 = new ArrayList<>();
        c3.add("A");
        c3.add("B");
        c3.add("C");
        c3.add("B");
        c3.add("C");
        c3.add("D");
        c1.equals(c3);
        System.out.println("c1和c3相同么:" + c1.equals(c3));

contains(Ojbect obj)  该方法的作用是判断集合中是否包含某一部分元素,使用对象名调用方法,返回值是boolean类型

containsAll(Collection c)该方法的作用是判断某一集合中是否包含其他集合,形参需要传入一个集合

equals()该方法的作用是判断两个集合是否相等,可以使用A.equals(B)的方式来判断,A,B都是集合对象,返回值是一个布尔类型

//9. boolean remove(Object o)  移除c1集合里的元素D,并查看剩余元素
        boolean remove = c1.remove("D");
        System.out.println("remove: "+remove);
        System.out.println("移除c1集合中的元素D:"+c1);

        //10.boolean removeAll(Collection <?> c)  新建一个集合c4,添加元素"B" "C"
        //从集合中删除另一个集合中所具有的元素,符合自己的元素都会删除
        //测试c1移除c4
        Collection<String> c4 = new ArrayList<>();
        c4.add("B");
        c4.add("C");
        System.out.println("c4: "+c4);
        c1.removeAll(c4);
        System.out.println("c1移除c4:"+c1);

        //11.boolean retainAll(Collection c )
        //作用:保留集合中符合另一个集合中的所有元素,不符合的删除
        //测试:向c1添加"E","F","G",然后保留子集c5,c5里的元素有"A","E"
        c1.add("E");
        c1.add("F");
        c1.add("G");
        Collection<String> c5 = new ArrayList<>();
        c5.add("A");
        c5.add("E");
        c1.retainAll(c5);
        System.out.println(c1);

        //12. void clear():  清空c1
        c1.clear();
        System.out.println(c1);
        System.out.println(c1.size());

remove(Ogject obj)

作用从集合中移除某个元素,返回值是一个布尔类型,查看移除操作是否成功,形参是需要移除的元素,用对象来调用;

removeAll(Collection <?> c)

作用从原集合中移除另一个集合中所具有的元素,符合条件的元素都会被移除,返回值是布尔类型,查看移除操作是否成功,形参是条件集合,用原集合对象来调用该方法;

retainAll (Collection c)

作用保留原集合中符合另一个集合中的所有元素,不符合条件的会被删除;返回值布尔类型,形参是条件集合,用对象名来调用

clear()

作用,清空集合中的所有元素,用集合对象来调用;

2.集合的迭代

集合的迭代就是指集合的遍历操作;几乎所有的集合子接口都实现了迭代接口Iterable;

迭代接口中提供了多个方法,用于迭代操作;-boolean hasNext(): 用于判断集合中是否有下一个元素。可以形象的理解为指针;指针的最初位置在第一个元素的前面,

-E next(): 用于返回指针指向的那个元素,然后指针向后移动,为下一次的判断做准备

-E remove(): 用于删除指针所指向的那个元素

需要注意的是,在使用迭代器时,不可以调用集合自己的remove()方法

public static void main(String[] args) {
        Collection<Integer> c1 = new ArrayList();
        c1.add(1);
        c1.add(2);
        c1.add(3);
        c1.add(4);
        c1.add(5);
        /**
         * 使用增强for循环(foreach)遍历:底层原理就是迭代器
         */
        for (Integer i : c1) {
            System.out.print(i + " ");
        }
        System.out.println();

在main方法中我们创建了一个集合并赋值1,2,3,4,5,首先使用增强for循环对集合进行遍历,定义一个Integer的对象来接收便利的结果,并将结果打印

之后我们使用迭代器的方式来对集合进行遍历;增强for循环的底层逻辑也是迭代器

//第一步:获取要遍历的集合对象的迭代器对象
            Iterator<Integer> it = c1.iterator();
            //第二步:问是否有下一个元素
            while (it.hasNext()) {
                //第三步:取元素
                Integer a = it.next();//此时指针向后移动
                System.out.println("a: " + a);
            }

首先需要定义一个迭代器对象,通过集合对象名.iterator()的方法来创建

3.List接口

List接口的特点:

1.元素有序并且可以重复

2.两个实现类:ArrayList  和  LinkedList    -ArrayList 动态数组和基本方法  -LinkedList 双向链表和各种方法

3.两个实现类在元素特别多的时候效率不同:

  -对于随机访问来说,ArrayList的效率高于LinkedList  -对于进行增删改来说,LinkedList的效率高于ArrayList。

4.这两个类都是基于List接口的,所以实现类的方法基本一致。

 //创建一个ArrayList集合对象
        List<String> names = new ArrayList<>();
        //创建一个linkedList集合对象
        List<String> adds = new LinkedList<>();

首先是创建集合的对象,都可以使用向上造型

 /**
         * 添加元素
         * boolean add(E e):  添加元素,默认向集合尾部添加
         * void add(int index, E  element) 插入元素,下标范围[0,size()]
         * boolean addAll(int index, Collection c)
         * boolean addAll(Collection  c )
         */
        names.add("micheal");
        names.add(0,"bob");
        names.add("aaa");
        names.add("bbb");
        names.add("ccc");
        System.out.println(names);

        //地址集合添加两个元素
        adds.add("beijing ");
        adds.add("shanghai ");

        //将地址集合添加到名字集合中
        names.addAll(adds);
        System.out.println(names);

添加元素与之前的方法基本一致,依旧是add( ), 和其重载的方法,addAll( ),和其重载的方法,在上述代码中,我们在names集合中添加了5个元素,在adds集合中添加了两个元素,并把adds集合的元素添加到names集合的元素尾部。

/**
         * E  get(int index) 获取元素
         */
        String s1 = adds.get(1);//得到上海
        System.out.println(s1);

        /**
         * 查找元素  int indexOf(Object obj)  返回指定元素的第一个下标,如果没有返回-1
         * 查找元素最后出现的位置  int lastIndexOf(Object obj)  返回指定元素的最后一个下标,没有返回-1
         */
        int i = names.indexOf("micheal");
        System.out.println(i);
        int i1 = names.lastIndexOf("bob");
        System.out.println(i1);

        /**
         * 移除元素  E  remove(int index)
         */
        adds.remove(1);
        System.out.println(adds);

        /**
         * 修改元素  E  set(int  index, E  element)
         */
         String add1 =  adds.set(0, "changchun");
        System.out.println("add1 "+add1);
        System.out.println(adds);

上述代码中的四个方法是比较基础的移除,修改,查找的方法,首先是get( )方法,形参是int类型的,需要传入集合的下标,返回值就是集合中的元素;如果需要查找元素所在的位置,需要使用indexOf方法,传入的参数是需要查找位置的元素,返回值类型是int,返回集合的下标,当然也可以使用lastIndexOf方法,返回的结果是该元素出现的最后一个下标,如果没有查找到该元素,就会返回-1;如果需要移除元素,可以使用remove( )方法,形参是元素的索引位置,返回值是被移除的元素,如果要修改集合中的内容,我们可以使用set( )方法,形参是索引位置和需要修改的元素;返回值是被替换的元素;

 /**
         * 截取子集 List subList(int fromIndex, int toIndex)
         * 用于截取子集,包前不包后
         */
         List n1 = names.subList(2,5);
         System.out.println(n1);
         List<Integer> nums = new ArrayList<>();
        for (int j = 1; j <11 ; j++) {
            nums.add(j);
        }
        System.out.println(nums);
        List<Integer> sub =  nums.subList(3,7);
        System.out.println(sub);

        //对子集里的每一个元素扩大10倍
        for (int j = 0;j<sub.size();j++) {
           //取出元素*10,然后替换掉原有的元素
//            int r = sub.get(j)*10;
            sub.set(j,sub.get(j)*10);
        }
        System.out.println(sub);
        System.out.println(nums);

截取子集的方法是 subList( ) 返回值是被截取的自己,需要传入两个形参,开始截取的索引和结束截取的索引,注意:包前不包后;

在创建集合的时候,我们还可以使用循环的方法来达到减少代码量的操作;比如需要创建一个都是数字的集合,就可以使用for循环创建一个长度为10的泛型为Integer的List集合;集合内容是从1到10的数字,之后对该集合进行截取,截取范围是3,7,会截取到4,5,6,7四个元素的集合,如果我们需要集合中的每个元素都扩大10倍的化,可以先获取到结婚中的每个元素并对其*10操作;然后再将将其放回到原集合中的每个索引位置;

4.队列Queue

队列Queue,也是Collection的子接口,用来描述一种先进先出的数据结构,可以理解为一种特殊的线性表,只能从一头进,另一头出,对应的方法:

-boolean offer(E e)  从队列的尾部插入元素;

-E  poll( ) 将队首的元素取出并移除这个元素;

-E  peek( ) 查看队首的元素;(只能查看,不能做其他操作)

//创建一个名字队列
        Queue<String> names = new LinkedList<>();
        //调用offer方法,入队
        names.offer("Micheal");
        names.offer("张三");
        names.offer("李四");
        //查看队列的样子
        System.out.println(names);
        //查看队列的头部对象
        String head = names.peek();
        System.out.println(head);
        System.out.println("=============================");

首先我们可以创建一个队列,泛型是String,调用offer方法,来添加元素;之后可以查看队列的头部元素,使用对象名.peek( )的方法

//如果想移除头部元素,最后先查看是否有头部元素,如果有再移除
        while (names.peek() != null) {
            String oldHead = names.poll();
            System.out.println(oldHead);
            System.out.println(names);
        }

如果我们想利用循环移除队列的头部元素;可以使用如上述代码的方法,循环条件是队列的头部元素不是空,就可以使用poll(  )方法,来移除队首的元素,并将其打印出来,之后再打印队列剩余的元素;

双端队列Deque:即可以从队列的两头添加元素,是Queue的子接口;对应的实现类,还是LinkedList

对应的方法: -offerFirst( ):   向队首添加元素    -offerLast( ) :  向队尾添加元素

                       -pollFirst( ) :   移除队首的元素     -pollLast( ):移除队尾的元素

 //创建一个双端队列
        Deque<String> names = new LinkedList<String>();
        //添加第一个元素
        names.offer("小明");
        //第二个元素从队列的头部进入
        names.offerFirst("小红");
        //第三个元素从队尾进入
        names.offerLast("小芳");
        System.out.println(names);

首先创建一个双端队列;,并向队列中添加元素,可以从队头添加,也可以从队尾添加

小红是从队首添加的所以再前面,小芳是从队尾添加的,所以在最后面

//移除元素
        //移除队列
        // 的头部元素
        String head = names.poll();
        System.out.println("head: "+head);
        //移除队列的尾部元素
        String tail = names.pollLast();
        System.out.println("tail: "+tail);
        System.out.println(names);

我们可以选择移除头部或者尾部的元素,默认是移除头部的元素

使用Deque来模拟栈结构;

 Deque <String> stack = new LinkedList<String>();

        //从栈的出口进入,方法是push,表示将元素推进去
        stack.push("micheal");//推入到栈的底部
        stack.push("lucy");//推入到最底层的上一层
        stack.push("lily");//推入到最底层的上一层的上一层
        stack.push("tom");//推入到最底层的上一层的上一层的上一层
        System.out.println(stack);

首先创建一个储存结构,储存类型是字符串类型的;从出口进入,使用push方法,将元素推入栈;需要注意:元素都应该是先进后出;之后出栈也应该是tom先出,之后是lily。。。

//出栈(弹出):对应的方法pop(),将元素弹出栈结构
        while(stack.size() > 0){
            String el = stack.pop();
            System.out.println(el);
        }

需要注意的是:在出栈的时候,需要调pop方法,可以使元素弹出栈;

5.Set接口

set接口,是collection的子接口;用来储存不重复的元素,元素的顺序是无序的,(取出的顺序和存入的顺序无关)(一旦存入,在结构中的顺序就固定了,和存入的先后顺序无关)

Set接口里的方法都是Collection接口中的方法,      -HashSet : 是实现了Set接口最最经典的子类型;  底层的储存方式就是Hash表

//创建一个Set接口的对象
        Set<String> names = new HashSet<String>();
        //存入micheal,lucy,john,tom
        names.add("michael");
        names.add("lucy");
        names.add("john");
        names.add("tom");
        System.out.println(names);
        /**
         * 打印一下四个元素的hash值
         */
        System.out.println("michael".hashCode()%16);
        System.out.println("tom".hashCode()%16);
        System.out.println("john".hashCode()%16);
        System.out.println("lucy".hashCode()%16);

首先创建一个Set接口的对象;存入四个元素,并打印这四个元素,然后分别打印这四个元素的hash值,发现这四个元素的哈希值不同,我们就是按照哈希值来排出他们的顺序的;

Set接口的去重原理: 先计算需要添加元素的哈希值,然后确定哈希表中该值的位置上是否存在元素,如果不存在,可以添加进集合中,如果存在,就需要使用equals方法进行比较,如果equals返回true,则不能添加,如果equals返回false,则可以添加,  需要注意:每一个哈希值的位置上,都维护了一个单向链表,可以储存进哈希值相同,但equals判断不同的元素;

boolean michael = names.add("michael");
        System.out.println(michael);
        System.out.println(names.size());
        System.out.println(names);

因为存入的元素与之前放入集合的元素哈希值和equals判断都相同,所以返回的结果肯定是false,无法添加;

hashSet的遍历

Set<Integer> set = new HashSet<Integer>();
        set.add(10);
        set.add(20);
        set.add(30);
        set.add(40);
        set.add(50);
        System.out.println(set);

首先创建一个集合,储存五个元素;因为Set集合中的元素是无序的,没有下标的意义,所以不能使用for循环来遍历,但是可以使用迭代器和增强for循环来遍历;

for (Integer i : set) {
            System.out.println(i);
        }
        System.out.println("=======");
        Iterator<Integer> it = set.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

第一个方法是增强for循环,创建一个变量来接受set中的每一个值,并打印,  第二种方法是使用迭代器,创建一个迭代器对象  it,然后询问it是否有下一个值,如果有就打印出下一个值。

这两种方式是等效的,因为增强for的底层就是迭代器。

public static void main(String[] args) {
        Set<String> set = new LinkedHashSet<>();
        set.add("A");
        set.add("B");
        set.add("C");
        set.add("bob");
        System.out.println(set);

        /**
         * 使用迭代器遍历
         */
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }

上述代码也是使用迭代器对set集合进行遍历;

TreeSet接口

TreeSet接口是SortSet接口的实现类,TreeSet集合内部存储的元素是有序的,并且不重复的,即内部维护了一个二叉树算法的排序方式,

默认的排序方式是升序,如果想用别的,需要使用比较器,重写比较方式

Set<String> set = new TreeSet<>();
        set.add("a");
        set.add("h");
        set.add("b");
        set.add("f");
        set.add("d");
        set.add("bob");
        set.add("bab");
        System.out.println(set);

先创建了一个TreeSet集合,向上造型,添加了元素,并打印出来,之前使用LinkedHashSet内容是无序的,这次是有序的,默认是升序,按照abcde的方式排列

Comparator c1=new Comparator<Integer>() {
        //创建比较器对象需要使用匿名内部类,重写里面的compare方法
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1; //降序排序
            }
        };
         Set<Integer> nums = new TreeSet<>(c1);
         nums.add(10);
         nums.add(1);
         nums.add(20);
         nums.add(2);
         System.out.println(nums);
    }

上述代码中我i们创建了一个TreeSet集合向上造型并传入了比较器对象c1,传入的元素就变成降序排列的了;

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

        //存入集合四个Person对象
        ps.add(new Person("michael",18));
        ps.add(new Person("john",18));
        ps.add(new Person("tom",18));
        ps.add(new Person("michael",18));
        System.out.println("ps : "+ ps);

        //需求:查看有没有一个叫Michael并且是18的人
        Person p1 = new Person("michael",18);
        Person p2 = new Person("michael",18);
        System.out.println(p1.hashCode());
        System.out.println(p2.hashCode());

在上述代码中,我们使用了自己定义的类来创建一个HashSet集合,添加了4个元素,并将其都打印出来,之后定义两个对象,来查看有没有叫michael的元素,然后查看hashCode值

因为对象的成员变量是固定的,所以hashCode值也相同。

之后我们再通过contains方法来判断集合中是否有p1元素

 /**
         *  调用contains方法,判断是否包含p1
         *  1.通过输出语句发现,返回的是false
         *    先调用hashCode,如果值不相同。就认为不存在
         *    如果值相同,还会调用equals方法进行比较,equals返回true,表示存在,否则表示不存在
         *
         *  2.结论:
         *    --在自定义类的时候,如果这个类的对象要存入Set集合中,需要重写hashCode和equals方法
         *    --基于上述需求,我们自定义的类就必须重写这两个方法。因为我们也不知道未来如何使用
         */
        boolean b = ps.contains(p1);
        System.out.println("集合中是否包含p1 :"+b);

在判断时,会先判断hashCode值,如果值不相同,则认为不存在,如果值相同,会调用equals方法来继续判断,返回true则表示存在,返回false则表示不存在

在自定义类的时候,如果这个类的对象需要储存在集合中,则需要重写hashCode( )和equals( )方法

Set接口中的删除操作

public static void main(String[] args) {
        Set<Person> set = new HashSet<Person>();

        Person p1 = new Person("小明",18);
        Person p2 = new Person("小张",19);
        Person p3 = new Person("小王",18);
        //存储进入集合
        set.add(p1);
        set.add(p2);
        set.add(p3);

首先创建一个新集合,并创建三个Person类对象,并把这三个对象储存进集合中;

 Person p4 = new Person("小王",18);
        set.add(p4);
        System.out.println(set);

因为我们重写了equals方法和hashCode方法,所以p4无法添加进集合中

 //修改p3的年龄为20岁
        p3.setAge(20);
        //
        Person p5 = new Person("小王",20);
        set.add(p5);
        System.out.println(set);

此时我们修改p3的年龄为20;然后发现可以继续添加一个元素p5和p3一样;

 set.remove(p3);
        //从结果上看,想删除p3,有一个和p3长得一样的元素没被干掉,把p5删除了
        System.out.println(set);

我们想要删除掉p3,但是无法删除p3,会在结果中把p5删除

这是因为我们在集合中修改了元素的属性后,会导致hashCode值不会发生改变,但是元素的属性的确改变了,我们在添加p5时,会有一个新的hashcode值存入,但是在进行删除p3的时候,会访问p3的属性,得到hashcode值,这个值是p5的值,所以会把p5删除,但是p3删除不掉了。

Sort排序

在我们自定义的类中,如果想实现排序,就要求元素必须是Comparable的子类型,因为底层需要调用Comparable的compareTo方法,所以,我们自定义的类,如果像排序,就必须实现Comparable接口,并重写里面的compareTo方法

在上述的基础上,如果我们想要重新定义比较规则,不应该修改compareTo方法的源代码,应该使用Comparator比较器来定义一个新规则,调用集合或者数组的方法来传入一个比较器的方法,从而进行一个新的排序。

集合工具类:Collections   数组工具类: Arrays

- void sort (List <E> list)

 - void sort(List<E> list,Comparator<E> c ): 可以使用比较器来重新制定比较规则

public static void main(String[] args) {
        List<Integer> list = new ArrayList<Integer>();
        for (int i = 0; i < 10; i++) {
            list.add((int)(Math.random() * 100));
        }
        System.out.println(list);
        /**
         * 利用工具类里的排序方法
         */
        Collections.sort(list);
        System.out.println(list);

在上述代码中,我们创建了一个集合,存入了一百以内的10个随机数,然后打印出来,并利用集合工具类的排序方法来直接排序

数组工具类的排序方法默认是升序排列,如果想使用降序排列,就需要使用比较器,采用匿名内部类的方式;

 Comparator c1 = new Comparator<Integer>() {
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        };
        Collections.sort(list, c1);
        System.out.println(list);

创建一个比较器对象c1,在里面重写compare方法,返回值是一个负数,然后使用集合工具类的sort方法把比较器对象传进去,对集合进行重新排序

集合中的其他工具类

 public static  void main(String[] args) {
        List<String> names = new LinkedList<String>();
                names.add ("michael");
                names.add("peter");
                names.add("mark");
                names.add("john");
                names.add("jane");

首先创建一个都是姓名的集合这个集合是LinkedList,是有序的

  1.打印集合,顺序为添加时的顺序
        System.out.println("初始结果"+names);

        //1.调用集合工具类里的反转方法
        Collections.reverse(names);
        System.out.println("反转后的结果:"+names);
        //2.调用工具类里的打乱方法
        Collections.shuffle(names);
        System.out.println("打乱后的结果:"+names);

之后我们可以打印集合,顺序就是添加元素的顺序,可以调用工具类的反转方法,reverse,集合元素的顺序会改变

可以调用打乱方法,让集合中的元素打乱;

//3.将第二个和倒数第二个元素交换
        Collections.swap(names,1,names.size()-2);
        System.out.println("交换后的结果"+names);

        //4.调用max方法:底层使用的自然排序,找到最大的
        String ele = Collections.max(names);
        System.out.println("最大的结果"+ele);

        //5.调用min方法:底层使用自然排序,找到最小的
        String ele2 =  Collections.min(names);
        System.out.println("最小的结果"+ele2);

可以调用swap方法,交换集合总的元素,形参是索引,调用max方法,根据自然排序得到最大的,也可以调用min方法,得到最小的元素;

 names.add("michael");
        names.add("michael");
        names.add("michael");
        System.out.println("集合:"+names);
        System.out.println("集合长度:"+names.size());

        //调用工具类找到michael出现的次数
        int count  = Collections.frequency(names,"michael");
        System.out.println("michael出现的次数:"+count);

我们可以在集合中继续添加三个Michael,并打印集合的长度和现在的集合,之后调用工具类的frequency方法来查看某一个元素出现的次数;形参是集合名,和需要查看的元素

//将集合中的所有Michael替换为张三
        Collections.replaceAll(names,"michael","张三");
        System.out.println("替换后的样子:"+names);

工具类中还有一个替换方法,将集合中某一元素替换为指定的元素

.

集合与数组之间的相互转换

集合转数组

 List<String> names = new ArrayList<>();
        names.add("michael");
        names.add("peter");
        names.add("mark");

首先创建一个List集合,泛型是String

 String[] arr = new String[0];
        String[] arr2 = names.toArray(arr);
        System.out.println(arr2.length);
        System.out.println(Arrays.toString(arr2));
        //判断第一个元素是不是以el结尾的
        String str2 = arr2[0];
        boolean el = str2.endsWith("el");
        System.out.println(el);

然后可以先创建一个String类型的空数组,之后调用集合名.toArray(T[ ]  t )的方法来将集合转变为某一类型的数组,该方法有返回值,就是一个该类型的数组,需要接收变量,之后我们可以打印新数组的长度,并展示一下里面的内容

之后我们可以判断第一个元素是不是以el结尾的,首先需要拿到数组中的第一个元素,然后调用字符串的方法.endsWith("el")来判断;返回的结果是true。

数组转集合

public static void main(String[] args) {
        String[] names = new String[5];
        names[0] = "michael";
        names[1] = "tom";
        names[2] = "lucy";
        names[3] = "lily";
        names[4] = "john";

首先创建一个长度为5的String类型的数组,并传入元素;

 List<String> list = Arrays.asList(names);
        System.out.println(list);
//        将集合的第二个元素替换为张三
        list.set(1,"张三");
        System.out.println(list);
        names[1] = "李四";
//        add和remove都属于修改集合的长度,会报错
        list.add("王五");
        list.remove(1);

然后我们使用集合工具类中的Arrays.asList方法将集合转换为数组;我们需要将集合中的第二个元素替换为张三,可以使用集合的set方法,将索引和张三传入即可,也可以选择直接使用索引来修改;但是,当我们使用add和remove方法时,程序会报错,因为我们不能对集合的长度进行修改,集合是由数组转换过来的,数组是不允许修改长度的。

如果想要添加新的元素,就必须将原集合中的元素拷贝到新集合中,再对其进行操作

ArrayList<String> list2 =new ArrayList<>(list);
        list2.add("张三");
        list2.add("李四");

创建一个新的数组,传入参数是list;向新数组添加张三和李四

//获取张三的位置
        int index = list2.indexOf("张三");
        Collections.swap(list2,0,index);
        System.out.println(list2);

之后我们可以获取张三的位置,使用indexOf方法,然后调用集合工具类中的swap方法调换张三和第一个元素的位置。

6.Map接口

Map接口是集合的另一大父接口

Map集合在储存数据时,一对一映射,是一个双列集合,内部是键值对(Entry)

Map接口的子类有HashMap和TreeMap:

HashMap底层使用的是Hash表和红黑树结构, TreeMap底层使用的是二叉树结构

Map的键是不可以重复的,但是值可以重复,我们可以通过键来找到具体对应的值,

Map中的元素也是无序的(在结构中的储存顺序和存入顺序无关)

 //创建一个Map集合(散列表)
        Map<String,Integer> map = new HashMap<>();
        //1.存储元素调用put方法
        map.put("张三",100);
        map.put("李四",98);
        map.put("王五",97);
        map.put("赵六",99);
        //输出打印一下
        System.out.println(map);

首先我们创建一个Map集合,调用集合的添加方法put 存入元素,在创建集合的时候,因为是键值对,我们需要传入两个泛型;

 //2.获取一个人的成绩  调用get(K k)
        Integer score = map.get("张三");
        System.out.println("张三的成绩"+score);

        //存入张三和60分     put方法,如果key相同,会覆盖掉原来的value
        map.put("张三",60);
        System.out.println(map);

        //取出小花的成绩    get(K k)方法  如果key不存在,返回null
        Integer score1 = map.get("小八");
        System.out.println("小八的成绩:"+score1);
         map.put(null,null);
        map.put(null,10);
        System.out.println(map);

之后我们可以获取键对应的值,调用get方法,输入的形参是键,返回值是值。如果我们在使用get方法时,输入的键不存你在,那么返回的值就是null,我们还可以调用put方法来修改键对应的值,如果输入的键和值都为null也可以储存进集合;如果put方法传入的键是集合中存在的,则是覆盖操作,会将原有的值覆盖,返回值是被覆盖的值。

Map的其他方法

 HashMap<String, String> course = new HashMap<>();
        course.put("王老师","语文");
        course.put("李老师","数学");
        course.put("张老师","化学");
        course.put("赵老师","生物");
        System.out.println(course);

首先创建一个Map集合;两个泛型都是String;并添加元素。

/**
         * 1. boolean isEmpty()
         */
        System.out.println("course集合是否为空 "+course.isEmpty());
        /**
         * 2. containsKey(Object obj)
         */
        System.out.println("是否包含张老师这个key "+course.containsKey("张老师"));
        /**
         * 3. containsValue(Object obj)
         */
        System.out.println("是否包含数学这个value "+course.containsValue("数学"));
        /**

判断集合是否为空可以使用  isEmpty()方法,返回值是布尔类型;

判断集合中是否包含某个键可以使用  containsKey(K k ),返回值是布尔类型

判断集合中是否包含某个值可以使用  containsValue(V v ) ,返回值是布尔类型

 /**
         * 4. V remove(K k)  移除一个键值对
         */
        course.remove("赵老师");
        System.out.println(course);
        /**
         * 5.  int size()
         */
        System.out.println(course.size());
        /**
         * 6.clear():  清空所有键值对
         */
        course.clear();
        System.out.println(course.size());
        System.out.println(course);

移除集合中某个键值对可以使用remove( )方法,传入的形参是键;

获取集合的长度可以使用  size( ) 方法,返回值类型是int

清空所有键值对可以使用  clear( )方法

Map集合的遍历

集合遍历的第一种方式(键找值)

遍历所有的键,通过键来找到对应的值,达到遍历整个集合的目的;

Map<String, Integer> scores = new HashMap<>();
        scores.put("michael", 100);
        scores.put("lucy", 98);
        scores.put("tom", 97);
        scores.put("john", 99);
 /**
         * 第一种方式:使用keySet():  返回所有key的set集合方式
         */
        Set<String> keys = scores.keySet();
        for (String key : keys) {
            //通过key获取value
            Integer value = scores.get(key);
            System.out.println(key + "--" + value);

        }
        System.out.println("===================");

首先创建一个只有键的单列集合遍历这个集合,通过调用每个键的value获得键值对;

集合遍历的第二种方式(entry键值对)

/**
         * 第二种方式: 使用entrySet(): 返回entry对象的set集合
         *     Entry: 是Map的内部类,Entry对象就是封装了一个键值对
         */
        Set<Map.Entry<String,Integer>>  es = scores.entrySet();
        for(Map.Entry<String,Integer> Entry :es){
            //每一个Entry都是键值对
//            System.out.println(Entry);
            /**
             * Entry类型提供了getKey()和getValue()方法
             */
            System.out.println(Entry.getKey()+"--"+Entry.getValue());
            System.out.println("=============");
        }

可以使用scores.entry();的方式创建一个集合对象,泛型是Map的内部类Entry<>,传入键和值的泛型,然后使用增强for循环对集合进行遍历;然后打印出键和值

使用第三种方式对集合进行遍历(获得每个值)

 Collection<Integer> values = scores.values();
        for(Integer value : values){
            System.out.println(value);
        }

直接调用scores.values()获得所有值,然后对这些值进行遍历;就可以得到所有的值的遍历结果;

LinkedHashMap

是hashMap的子类型,使用链表维护了元素的插入顺序,确保集合是有序的;

public static void main(String[] args) {
        Map<String, String> map = new LinkedHashMap<>();
        map.put("张三","北京");
        map.put("李四","上海");
        map.put("王五","北京");
        map.put("赵六","长春");
        System.out.println(map);
    }

TreeMap

使用二叉树对key进行排序,默认是升序,可以通过比较器来自定义比较规则;

public static void main(String[] args) {
        Comparator c1 = new Comparator<String>() {
            public int compare(String o1, String o2) {
                return -o1.compareTo(o2);
            }
        };


        Map<String,Integer> map = new TreeMap<>(c1);
        map.put("A", 100);
        map.put("a", 90);
        map.put("b", 80);
        map.put("C", 90);
        System.out.println(map);

    }

首先创建一个比较器对象,重写比较方法;之后创建集合,输入集合中的元素

  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值