集合

176 阅读7分钟

集合

集合框架


     // 集合框架

    /*  1. collection : 存储一个人一个的数据

 --------子接口 List: 存储有序的 可重复的数据

---------ArrayList(主要的实现类):线程不安全,效率高,底层用的Object[]数组储存
                        在添加数据,查找数据效率高 在插入 删除数据效率低

----------LinkedList  :底层用的双向链表的方式储存 在对集合进行频繁 插入 删除 使用
          在添加数据,查找数据效率低 在插入 删除数据效率高

----------Vector: List古老的实现类  线程安全,效率低,底层用的Object[]数组储存

    ---------子接口 Set : 存储无序的 不可重复的数据      常用方法 为Collection 声明的15个方法

    -------------HashSet(主要的实现类)       使用数组 单向链表 红黑树 的结构进行存储  (要重写equals  hashcode)

       ------------LinkedHashSet : HashSet的子类  使用数组 单向链表 红黑树  的基础上有添加了一组双向链表  (要重写equals  hashcode)
                                                用于记录添加元素的先后顺序 即按照添加元素的顺序进行遍历 便于频繁查寻


       ---------------TreeSet  底层使用红黑树的结构  按照添加元素的指定属性的大小进行遍历


     2.Map   : 存储一对一对的数据 (key--values  函数对应关系)

---------HashMap(主要的实现类) 线程不安全,效率高  可以添加null 的key和value的值  代码健壮性强   使用数组 单向链表 红黑树 的结构进行存储
    ---------------  LinkedHashMap:  HashMap的子类在HashMap的数据结构基础上添加了个双向链表 用于记录添加元素的先后顺序,
    //                                  进而在遍历的时候,按添加元素的顺序显示   开发中,对于遍历操作 建议使用此类

------------------TreeMap:  底层使用红黑树的结构 可以按照添加的key--values元素的指定的属性的大小顺序进行遍历 需要考虑自然排序和定制排序



------------------Hashtable:古老的实现类  线程安全,效率低,不可以添加null 的key或value的值   使用数组 单向链表 的结构进行存储
          ------------------Properties key--values元素都是String类型  常处理属性文件


            HashMap元素的特点
            1.HashMap中的所有的key彼此之间是不重复的,无序的所有的key构成一个Set集合  需要重写equals  hashcode
            2.HashMap中的所有的values彼此之间是可以重复的,无序的所有的key构成一个Collection集合  需要重写equals
            3.HashMap中的key-values构成entry Hash Map中的entry彼此之间是无序的,不可重复的,所有的entry构成Set集合

     */

    

1. collection

Collection接口实现类的特点
public interface Collection extends Iterable

(1)Collection实现子类可以存放多个元素,每个元素可以是Object
(2)有些Collection的实现类,可以存放重复的元素,有些不可以
(3)有些Collection的实现类是有序的(List),有些是无序的(Set)–这里说的有序和无序是指取出的顺序是否和放入顺序一致
(4)Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的

collection的基本方法
     增:add添加元素  addAll


        删:.remove 删除指定的元素   remove(int index) 删除指定为位置的元素


        改: set(int index,Object ele)


        查:get(int index)


        插: add(index ,Object ele)   addAll(index ,Collection eles)

        长度: size

        遍历:  增强for循环  .Iterator  迭代器遍历集合元素
                // 1.add添加元素  addAll  size 长度
      //  ArrayList<Object> objects = new ArrayList<>();
        Collection coll = new ArrayList();
        coll.add("酷盖");
        coll.add(520);
         coll.add("奶盖");
         coll.add(new Person ("奶盖",18));
        System.out.println(coll);

         Collection coll1= new ArrayList<>();
//         coll1.add(1314);
//         coll1.add(45);
         coll1.add(520);
        coll1.add(new Person ("奶盖",18));
//         coll.addAll(coll1);
//        System.out.println(coll +" " + coll.size());  //五个数据
        //if 用add
//        coll.add(coll1);
//        System.out.println(coll.size() + " " + coll);  // 四个数据 coll1 当成一个数据

        //2.isEmpty  判断是否为空
        System.out.println(coll.isEmpty());

        //3.contains  判断有无该元素
        System.out.println(coll.contains(520));
        //4.containsAll 判断是不是该对象的子集
        System.out.println(coll.containsAll(coll1));  // 注意如果有对象内容比较 要通过重写equals 方法

        //5.void clear  清空元素
        coll1.clear();
        System.out.println(coll1);
        //6.remove 删除指定的元素   remove(int index) 删除指定为位置的元素

        coll.remove(520);
        System.out.println(coll);
        //7.removeAll(Collection coll)删除两个集合相同的元素
        //8.retainAll(Collection coll)删除两个集合不相同的元素

        //9.Object[] toString  返回当前集合所有元素的数组
        Object[] array = coll.toArray();
        System.out.println(Arrays.toString(array));
        //10 Array.asList     数组转成集合
      //  int arr0[] = new int[] {1,2,4,5,};
        String arr0 [] = {"1","2"};
         Collection  list = Arrays.asList(arr0);
        System.out.println(list);
        System.out.println("=============");


        //11.Iterator  迭代器遍历集合元素    获取迭代器    coll(已创建的集合).iterator。var
        // 实现遍历  while(iterator.hasNext()){  iterator.nest();   } 1.指针下移 2.下移后的集合元素返回

        Iterator iterator = coll.iterator();
        for(int i = 0;i < coll1.size();i++){
            System.out.println(iterator.next());
        }

        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //错误写法
//        while (iterator.next() != null){
//            System.out.println(iterator.next());
//        }


        //12 增强for循环
        //作用  遍历数组 集合   对于集合来讲  底层用的仍然是迭代器
        for(Object obj : coll){  // 先写类型 再编写一个变量名  : 遍历的对象
            System.out.println(obj);
        }
        // 增强for循环将元素依次赋给临时变量  注意 在循环体中对临时变量的修改,可能不会导致原有集合和数组的元组改变


        /*
List:存储有序的 可重复的数据
List接口是Collection接口的子接口
(1)List集合类中元素有序(即添加顺序和取出顺序一致)、并且可以重复
(2)List集合中的每个元素都有其对应的顺序索引,即支持索引
(3)List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
(4)List接口的常用实现类有:ArrayList、LinkedList和Vector
—
    //addAll  增填元素在某个位置
         List list = new ArrayList();  //创建对象
         list.add("奶盖");
         list.add("520");
         list.add("酷盖");
         list.add(2,1314);
        System.out.println(list);

         List list1  = new ArrayList();
         list1.add(1314);
         list1.add(45);
         list.addAll(3,list1); // 多个元素  不看做为一个整体
        System.out.println(list);

        List list2 = Arrays.asList(1,2,3);
        list.add(3,list2); //*** add 当作一个整体
        System.out.println(list);//[奶盖, 520, 1314, [1, 2, 3], 1314, 45, 酷盖]
        list.addAll(3,list2);
        System.out.println(list);//[奶盖, 520, 1314, 1, 2, 3, [1, 2, 3], 1314, 45, 酷盖]

        list.remove(0); // 索引
        System.out.println(list);
        System.out.println(list.get(2));
        list.remove( Integer.valueOf(2));// 删除对象2
        System.out.println(list);

        int i = list.indexOf(1);  // 查找索引

        System.out.println(i);


        //遍历
        Iterator iterator = list.iterator();  //创建对象
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        for (Object obj : list){
            System.out.println(obj);
        }


    }
}
Set接口和常用方法
(1)无序(添加和取出的顺序不一致),没有索引
(2)不允许元素重复,所以最多包含一个null
(3)JDK API中Set接口的实现类有:

Set接口的遍历方式
同Collection的遍历方式一样,因为Set接口是Collection接口的子接口。
1.可以使用迭代器
2.增强for循环
3.不能使用索引的方式来获取
常用方法和list基本差不多
    
 
treeset
    package Gather;

import java.util.Comparator;
import java.util.Objects;

public class TreeSet {
    public static void main(String[] args) {

        //TreeSet  底层使用红黑树的结构  按照添加元素的指定属性的大小进行遍历
        // 要求: 添加的元素必须是同一类型的对象 否则会报错

        //判断元素是否相同 不在考虑equals  hashcode
        //比较的标准是 自然排序  和定制排序  compareTo的返回值  如果返回值是0 则两个对象相等 返回第一个


//      set.add("A");
//      set.add("a");
//      set.add("Z");
//      set.add("J");
//      set.add("P");
        // set.add(1);
        // java.util.TreeSet set = new java.util.TreeSet();//  无参自然排序
        Comparator comparator = new Comparator() { // 定制排序*******************************  // 比自然排序多样

            @Override
            public int compare(Object o1, Object o2) {
                if (o1 instanceof Student && o2 instanceof Student) {
                    Student student1 = (Student) o1;
                    Student student2 = (Student) o2;
                    int value = student1.getAge() - student2.getAge();
                    if (value != 0) {
                        return value;
                    } else
                        return student1.getName().compareTo(student2.getName());
                }
                throw new RuntimeException("输入异常");


            }
        };
        java.util.TreeSet set = new java.util.TreeSet(comparator);//  有参定制排序
        Student s1 = new Student("sam", 22);
        Student s2 = new Student("sa", 18);
        Student s3 = new Student("DaMing", 18);
        Student s4 = new Student("jack", 23);
        set.add(s1);
        set.add(s2);
        set.add(s3);
        set.add(s4);

        for (Object obj : set
        ) {
            System.out.println(obj);

        }

    }

}

class Student implements Comparable {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
//    @Override
//    public boolean equals(Object object) {
//        if (this == object) return true;
//        if (object == null || getClass() != object.getClass()) return false;
//        student student = (student) object;
//        return age == student.age && Objects.equals(name, student.name);
//    }

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

 //   @Override
    public int compareTo(Object o) {//******************** 自然排序********************************************

        if (this == o) {
            return 0;
        }
        if (o instanceof Student) {
            Student student = (Student) o;
            int n = -(this.age - student.age);  // 从大到小
            if (n != 0) {
                return n;
            } else
                return this.name.compareTo(((Student) o).name);

        }
        throw new RuntimeException("输入的类型错误");

    }


}






2.Map

Map集合
Map接口实现类的特点
(1)Map与Collection并列存在,用于保存具有映射关系的数据Key-Value(双列元素)
(2)Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
(3)Map中的key不允许重复,原因和HashSet一样,前面分析过源码。
(4)Map中的value可以重复
(5)Map的key可以为null,value也可以为null,注意key为null,只能有一个,value为null可以多个
(6)常用String类作为Map的key
(7)key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value
(8)Map存放数据的key-value示意图,一对key-value 是放在一个Node中的,又因为Node实现了Entry接口,有些书上也说一对key-value就是一个Entry


   // HashMap的方法
        /*
        增:  put(Object key, Object values)
              putAll(MAp m)

        删:  Object remove(Object key)

        改:  put((Object key, Object values)
               putAll(MAp m)  覆盖

        查:  Object get(Object key)

        长度: size

        遍历:遍历key 集 Set keySet()
             遍历values Collection values()
             遍历entry  Set  entry()

         */
        // 增
        HashMap map = new HashMap();
        HashMap map1 = new HashMap();
        map.put(1,"8");
        map.put("奶盖",23);
        map.put("酷盖",22);
//        map1.put("盖",23);
//        map1.put("酷5盖",22);
//        map.putAll(map1);
        System.out.println(map);

        // 删
        map.remove(2);
        System.out.println(map);
        // 改
        map.put("酷盖",45);
        System.out.println(map);
        // 查
        map.get(1);
        System.out.println(map.get(1));

        // 遍历
        Set keySet = map.keySet();
        for (Object obj : keySet){
            System.out.println(obj);
        }

        Collection values = map.values();
        for (Object obj: values
             ) {
            System.out.println(obj);
        }
        Set  entry = map.entrySet();
        for (Object obj: entry
             ) {
            System.out.println(obj);
        }


    }
}

HashMap小结
Map接口的常用实现类:HashMap、Hashtable和Properties
HashMap是Map接口使用频率最高的实现类
HashMap是以key-value 对的方式来存储数据(HashMap$Node类型)
key不能重复,但是值可以重复,允许使用null值和null键(null键只能有1个)
如果添加相同的key,则会覆盖原来的key-val,等同于修改(key不会替换,val会替换)
与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的。
HashMap没有实现同步,因此是线程不安全的,方法没有做同步互斥的操作,没有synchronized