2020-10-25 java------------------ collection集合

在这里插入图片描述
ArrayList、LinkedList、Vector和Stack是List的四个实现类,其中Vector是基于JDK1.0,虽然实现了同步,但是效率低,已经不用了,Stack继承与Vector,所以不再赘述。
LinkedList是个双向链表,它同样可以被当作栈、队列或双端队列来使用。

collection

在类中重写tostring方法,可以在该类对象println时输出字符值而不是地址值(因为类的积累object包含tostring方法),println在输出对象时默认调用tostring方法

集合可以存储不同类型元素,集合只能存储对象,集合长度可变。

collection是集合的顶层接口,他的子体系有list(有序的)(有序是指插入顺序和取出顺序一样),有set(不能重复的)等等,list下有arrylist vector linkedlist等,set下有hashset treeset等

arrylist底层是数组,查询快,增删慢。线程不安全,效率高
vect底层数据结构是数组,查询快,增删慢。线程安全,效率低
linkedlist底层数据结构是链表,查询慢,增删快。线程不安全,

collection常用方法
removeall只要有一个元素移出就返回true
retainall求两个集合交集,谁调用谁就被改变。返回值返回的是调用的集合有没有发生改变

iterator迭代器使用

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class StudentDemo {
    public static void main(String[] args) {
        Collection c=new ArrayList(); /创建集合
         Student S1=new Student("何艳莹",18);
         Student S2=new Student("羊亚红",18);
         Student S3=new Student("小羊",19);
        Student S4=new Student("羊亚ya红",18);
        Student S5=new Student("小xiao羊",19);
        c.add(S1);
        c.add(S2);
        c.add(S3);
        c.add(S4);
        c.add(S5);
        Iterator it=c.iterator();   获取迭代器对象
        while (it.hasNext()){
//            System.out.println(it.next());


//            Exception in thread "main" java.util.NoSuchElementException   不要多次使用it.next,出现这个错误是因为next类似指针每次。next都往后移动
//            at java.util.ArrayList$Itr.next(ArrayList.java:862)          偶数不会报错,奇数报错
//            at StudentDemo.main(StudentDemo.java:21)

            System.out.println(((Student) it.next()).getName()+"-----"+((Student) it.next()).getAge());
        }

    }
}

报错:Exception in thread “main” java.util.NoSuchElementException
原因如注释
注意:迭代器是接口不是类。

List

List是有序可重复的collection,此接口使用户可以对列表每个元素的插入位置进行精准控制

import java.util.ArrayList;

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

public class StudentDemo {
    public static void main(String[] args) {
        List list = new ArrayList();
        //向上转型
        list.add("hello");
        list.add("world");
        list.add("heyanying");
        list.add("beaf");
        list.add("hello");    //可重复

        Iterator it = list.iterator();
        while (it.hasNext()) {
//            String s = (String) ita.next();    想要自定义输出形式就要向下转型
            System.out.println((String)it.next());
        }
    }
}

为啥要把arrylist向上转型成list

比如写一个方法,参数要求传递List类型,你就可以用List list = new ArrayList()中的list传递,但是你写成ArrayList list = new ArrayList()是传递不进去的。尽管方法处理时都一样。另外,方法还可以根据你传递的不同list(ArrayList或者LinkList)进行不同处理。
list常用方法
add
get 获取元素
ListIterator 列表迭代器
ListIterator(int index)获取指定位置的迭代器
remove 删除
set (int index,object elemen)修改指定位置元素

listlterator用法展示

import javax.swing.text.html.HTMLDocument;
import java.util.*;

public class StudentDemo {
    public static void main(String[] args) {
        List lista = new ArrayList();
        Collection list=new ArrayList();
        //向上转型
        list.add("11");
        list.add("22");
        list.add("33");
        lista.add("hello");
        lista.add("world");
        lista.add("heyanying");
        lista.add("beaf");
        lista.add("hello");    //可重复
        lista.remove(0);
        lista.set(0, "hahaha");
//        System.out.println("get:"+lista.get(2));
//        Iterator it = list.iterator();
//        while (it.hasNext()) {
            String s = (String) ita.next();    想要自定义输出形式就要向下转型
//            System.out.println((String) it.next());
//        }
        Iterator it=list.iterator();
        while (it.hasNext()){
            System.out.println((String)it.next());
        }
        System.out.println("--------------------");
        ListIterator ita=lista.listIterator();   //实现了iterator接口,list特有,可以往前移动
        while (ita.hasNext()){
            System.out.println((String)ita.next());
        }
        System.out.println("--------------------");
        while (ita.hasPrevious()){
            System.out.println((String)ita.previous());

        }
//        11
//        22
//        33
//                --------------------
//        hahaha
//        heyanying
//        beaf
//        hello
//        --------------------
//        hello
//        beaf
//        heyanying
//        hahaha
//
    }
}

Exception in thread “main” java.util.ConcurrentModificationException
at java.util.ArrayList I t r . c h e c k F o r C o m o d i f i c a t i o n ( A r r a y L i s t . j a v a : 909 ) a t j a v a . u t i l . A r r a y L i s t Itr.checkForComodification(ArrayList.java:909) at java.util.ArrayList Itr.checkForComodification(ArrayList.java:909)atjava.util.ArrayListItr.next(ArrayList.java:859)
at StudentDemo.main(StudentDemo.java:18)

并发修改异常产生原因

import javax.swing.text.html.HTMLDocument;
import java.util.*;

public class StudentDemo {
    public static void main(String[] args) {
        List list=new ArrayList();
        //向上转型
        list.add("11");
        list.add("22");
        list.add("33");


        Iterator it=list.iterator();
        while (it.hasNext()){
            if("33".equals(it.next()))  //集合增加元素而迭代器不知
                list.add("success");
            System.out.println((String)it.next());
        }

    }
}

解决方法
a:让迭代器修改元素
b: 集合遍历,集合修改

import javax.swing.text.html.HTMLDocument;
import java.util.*;

public class StudentDemo {
    public static void main(String[] args) {
        List list=new ArrayList();
        //向上转型
        list.add("11");
        list.add("22");
        list.add("33");


//        Iterator it=list.iterator();
//        while (it.hasNext()){
//            if("22".equals(it.next()))
//                list.add("success");
//            System.out.println((String)it.next());
//        }
        ListIterator lit=list.listIterator();
        while (lit.hasNext()){
            if("".equals(lit.next()))
                lit.add("success");   //   list.add("success")
        }
        System.out.println((list));

    }

}
//  [11, 22, success, 33]
//集合遍历可插在最后

iterator和listiterator区别

一、ListIterator有add()方法,可以向List中添加对象,而Iterator不能。

二、ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历。但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。

三、ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator 没有此功能。

四、都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iterator仅能遍历,不能修改。因为ListIterator的这些功能,可以实现对LinkedList等List数据结构的操作。

ArryList

ArrayList类是一个特殊的数组–动态数组。来自于System.Collections命名空间;通过添加和删除元素,就可以动态改变数组的长度。

优点:

1、支持自动改变大小
2、可以灵活的插入元素
3、可以灵活的删除元素

局限:

比一般的数组的速度慢一些;

用法

一、初始化:

1、不初始化容量

ArrayList arr1 = new ArrayList(); //不初始化刚开始的数组容量,当数组容量满时数组会自动一当前数组容量的2倍扩容

2、初始化容量

ArrayList arr2 = new ArrayList(3);//初始容量为3

3、用一个集合或数组初始化

ArrayList arr3 = new ArrayList(a);        //a为集合或数组
ArrayList list = new ArrayList(Arrays.asList(-10,-3,0,5,9));

LinkedList

Java的LinkedList是一种常用的数据容器,与ArrayList相比,LinkedList的增删操作效率更高,而查改操作效率较低。
LinkedList是个双向链表,它同样可以被当作栈、队列或双端队列来使用
LinkedList 实现了List 接口,能对它进行列表操作。
LinkedList 实现了Deque 接口,即能将LinkedList当作双端队列使用。
LinkedList 实现了Cloneable接口,能克隆。
LinkedList 实现了java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
构造方法

  1. LinkedList() 用于创建一个新的空linkedList;
  2. LinkedList(Collection<? extends E> c) 使用一个集合创建一个新的linkedList。
public class Main {
    public static void main(String[] args) {
        LinkedList<String> linkedList1 = new LinkedList<>();
        System.out.println(linkedList1);
        String[] arr = {"H", "E", "L", "L", "O"};
        LinkedList<String> linkedList2 = new LinkedList<>(Arrays.asList(arr));
        System.out.println(linkedList2);
    }
}

Set

package cn.itcast_01;
/*
collection:
list有序是指存储顺序和取出顺序一致,可重复
set无序是指存储顺序和取出顺序不一致,唯一
    hashset不保证set迭代顺序,不能保证该顺序恒久不变
       linkedhashset底层是hash表和链表(存储和取出顺序一致)
 */

import java.util.HashSet;
import java.util.Set;

public class SetDemo {
    public static void main(String[] args) {
        Set<String> set=new HashSet<String>();
        set.add("hello");
        set.add("java");
        set.add("ee");
        set.add("java");
        set.add("ee");
        for(String i :set){
            System.out.println(i);
        }

    }
}
/*
元素唯一且无序
ee
java
hello
 */

HashSet

的唯一性是通过hashcode和equals实现的,其实是哈希表结构,元素hash值相同并且元素值相同不会加入。
注意string类重写了hashcode和equals方法所以可以比较出相同,如果不重写一般不相同。如下

package cn.itcast_01;

import java.util.HashSet;
import java.util.Set;

public class SetDemo {
    public static void main(String[] args) {
        Set<Student> set=new HashSet<Student>();
        Student s1=new Student("小红",18);
        Student s2=new Student("小黄",18);
        Student s3=new Student("小红",20);
        Student s4=new Student("小黑",18);
        Student s5=new Student("小红",18);
        set.add(s1);
        set.add(s2);
        set.add(s3);
        set.add(s4);
        set.add(s5);
        for( Student i :set){
            System.out.println(i.toString());
        }

    }
}
/*
元素重复
Student{name='小红', age=20}
Student{name='小红', age=18}
Student{name='小黄', age=18}
Student{name='小红', age=18}
Student{name='小黑', age=18}
 */
 @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

Student{name=‘小黄’, age=18}
Student{name=‘小红’, age=18}
Student{name=‘小红’, age=20}
Student{name=‘小黑’, age=18}
没有重复了

TreeSet

能够按照某种顺序给元素排序(选哪个取决于用哪个构造方法)
A:自然排序 -------实现compareable接口重写compareto方法
B:比较器排序 (常见)

无参构造默认自然排序

自然排序 -------实现compareable接口重写compareto方法

package cn.itcast_01;

import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

public class SetDemo {
    public static void main(String[] args) {
        TreeSet<Integer> ts=new TreeSet<>();  //无参构造默认自然排序
        ts.add(3);
        ts.add(1);
        ts.add(23);
        ts.add(15);
        ts.add(15);
        for( Integer i :ts){
            System.out.println(i);
        }

    }
}
/*
1
3
15
23
 */
public class SetDemo {
    public static void main(String[] args) {
        TreeSet<Student> set=new TreeSet<Student>();
        Student s1=new Student("小红",18);
        Student s2=new Student("小黄",18);
        Student s3=new Student("小红",20);
        Student s4=new Student("小黑",18);
        Student s5=new Student("小红",18);
        set.add(s1);
        set.add(s2);
        set.add(s3);
        set.add(s4);
        set.add(s5);
        for( Student i :set){
            System.out.println(i.toString());
        }

    }
}
/*
报错:lang.ClassCastException: cn.itcast_01.Student cannot be cast to java.lang.Comparable
类要实现自然排序就必须实现自然排序接口
 */

类要实现自然排序就必须实现自然排序接口重写的compareto方法要自己写

  public int compareTo(Student o) {
    //    return 0;  因为底层是红黑树,比根节点小往左子树大往右子树,所以比较得0认为相同大小不会插树 只存进去一个根节点 Student{name='小红', age=18}
     //    return 1;  同理,怎么进怎么出
        // return -1; 按输入顺序倒着输出
        //实际应该按照排序规则返回

    /*    int num=this.age-o.age;
        return num;
   结果:年龄相同名字相同的也无法存进来
   Student{name='小红', age=18}
   Student{name='小红', age=20}
     */
    int num1=this.age-o.age;
    int num=num1==0?this.name.compareTo(o.name):num1;  //字符串自带compareto
    return num;
    }

按照名字比较只需改写类的compareto

 @Override
    public int compareTo(Student o) {
    int num1=this.name.length()-o.name.length();
    int num=num1==0?this.name.compareTo(o.name) :num1;
    return num;
    }
 public static void main(String[] args) {
        TreeSet<Student> set=new TreeSet<Student>();
        Student s1=new Student("小红",18);
        Student s2=new Student("小黄黄黄黄黄",18);
        Student s3=new Student("小红红",20);
        Student s4=new Student("小黑黑黑黑",18);
        Student s5=new Student("小红",19);
        set.add(s1);
        set.add(s2);
        set.add(s3);
        set.add(s4);
        set.add(s5);
        for( Student i :set){
            System.out.println(i.toString());
        }
/*
Student{name='小红', age=18}
Student{name='小红红', age=20}
Student{name='小黑黑黑黑', age=18}
Student{name='小黄黄黄黄黄', age=18}
实现从高到底排序只需要交换是this o
*/

但是这样名字一样并且长度一样的人年龄不同也不一定是一个人,比如19岁的小红没加进去

@Override
    public int compareTo(Student o) {
    int num1=this.name.length()-o.name.length();
    int num2=(num1==0?this.name.compareTo(o.name) :num1);
    int num3=(num2==0?this.age-o.age:num2);

    return num3;
    }
/*
Student{name='小红', age=18}
Student{name='小红', age=19}
Student{name='小红红', age=20}
Student{name='小黑黑黑黑', age=18}
Student{name='小黄黄黄黄黄', age=18}
*/

比较器排序

public class MyComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
       int num1=o1.getName().length()-o2.getName().length();
       int num2=(num1==0?o1.getName().compareTo(o2.getName()) :num1);
       int num3=(num2==0?o1.getAge()-o2.getAge():num2);
       return num3;
    }
}
public static void main(String[] args) {
//        TreeSet<Student> set=new TreeSet<Student>();
        TreeSet<Student> set=new TreeSet<Student>(new MyComparator());  //接口类型的参数传一个实现该接口的类的实例
        Student s1=new Student("小红",18);
        Student s2=new Student("小黄黄黄黄黄",18);
        Student s3=new Student("小红红",20);
        Student s4=new Student("小黑黑黑黑",18);
        Student s5=new Student("小红",19);

实现从高到底排序只需要交换是s1 s2
只用一次就造个类很浪费,匿名内部类正好解决

 public static void main(String[] args) {
//        TreeSet<Student> set=new TreeSet<Student>();
        TreeSet<Student> set=new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int num1=o1.getName().length()-o2.getName().length();
                int num2=(num1==0?o1.getName().compareTo(o2.getName()) :num1);
                int num3=(num2==0?o1.getAge()-o2.getAge():num2);
                return num3;
            }
        });

        Student s1=new Student("小红",18);
        Student s2=new Student("小黄黄黄黄黄",18);
        Student s3=new Student("小红红",20);
        Student s4=new Student("小黑黑黑黑",18);
        Student s5=new Student("小红",19);

匿名内部类格式
new类名或接口名,大括号里面重写方法(此例子中接口是泛型)

一定要注意,给了排序标准后还要考虑潜在的
比如按总分排序,那总分一样的并不一定是一个人,还要看语数英等
Integer.parseint()可以把string类型转换成int类型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值