集合框架回顾

集合

对象的容器,定义了对多个对象进行操作的常用方法,可以实现数组的功能

和数组的区别:

  1. 数组长度固定,集合长度不固定

  2. 数组可以存储基本类型和引用类型,集合只能存储引用类型

Collection体系集合

Collection 该体系结构的根接口 代表一组对象 称为集合

List接口 有序 有下标 元素可以重复

set接口 无序 无下标 元素不能重复

Collection父接口

特点:代表一组任意类型的对象,无序,无下标,不能重复

方法:

  • boolean add(Object obj)//添加一个对象

  • boolean addAll(Collecttion 从)//将一个集合中的所有对象添加到此集合中

  • void clear()//清空此集合中的所有对象

  • boolean contains(Object o) //检查此集合中是否含有o对象

  • boolean equals(Object o) //班级此集合是否和指定对象相等

  • boolean isEmpty() //判断集合是否为空

  • boolean remove(Object o) //在此集合中移除o对象

  • int size() //返回此集合中元素的个数

  • Object[] toArray() //将此集合装换成数组

package CollectionFramework;
​
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
​
public class TestCollection {
​
    public static void main(String[] args) {
        //创建集合
        Collection collection = new ArrayList();
        //添加元素
        collection.add("苹果");
        collection.add("香蕉");
        collection.add("西瓜");
        System.out.println("元素个数:"+collection.size());//3
        System.out.println(collection);//[苹果, 香蕉, 西瓜]
        //删除元素
//        collection.remove("西瓜");
//        System.out.println(collection);//[苹果, 香蕉]
//        collection.clear();
//        System.out.println(collection);//[]
        //遍历元素
        //增强for
        for (Object o : collection) {
            System.out.println(o);
        }
        //迭代器  专门用来遍历集合的一种方式
        //hasNext()  有没有下一个元素
        //next()   获取下一个元素
        //remove()  删除当前元素
        Iterator iterator = collection.iterator();
        while (iterator.hasNext()){
            //在迭代过程中 不能使用collection的其他方法来改变元素
            String s = (String) iterator.next();
            System.out.println(s);
//            collection.remove(s);不能使用这个删除
//            iterator.remove();//可以使用这个
        }
​
        //判断
        System.out.println(collection.contains("西瓜"));//有没有西瓜
        System.out.println(collection.isEmpty());//是否为空
​
    }
​
}
​
​
package CollectionFramework;
​
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
​
public class TestCollection02 {
​
    public static void main(String[] args) {
        //新建Collection对象
        Collection collection = new ArrayList();
        Student student1 = new Student("张三", 18);
        Student student2 = new Student("张四", 19);
        Student student3 = new Student("张五", 25);
​
        collection.add(student1);
        collection.add(student2);
        collection.add(student3);
​
        System.out.println(collection.size());
        System.out.println(collection.toString());
​
        //删除
//        collection.remove(new Student("张三",18));//这样是无法删除的,因为new已经新建了一个对象,和以前的对象无关
//        collection.remove(student2);
//        collection.clear();//只是把对象从集合中移除,对象本身还是存在
        System.out.println(collection);
​
        //遍历
        for (Object o : collection) {
            Student student = (Student)o;
            System.out.println(student);
        }
​
        Iterator iterator = collection.iterator();
        while (iterator.hasNext()){
            Student s = (Student) iterator.next();
            System.out.println(s);
        }
​
        //判断
        System.out.println(collection.contains(student1));//true
        System.out.println(collection.contains(new Student("张三",18)));//false
        System.out.println(collection.isEmpty());
    }
​
}
​

List集合

有序(添加的顺序和遍历顺序一样 有下标 元素可以重复

方法:

  • void add(int Index ,Object o) 在Index位置插入o对象

  • boolean addAll(int Index,Collection c) 将一个集合中的元素添加到该集合中的Index位置

  • Object get(int index) 返回集合中指定位置的元素

  • List subList(int fromIndex , int toIndex) 返回fromIndex 和 toindex之间的集合元素

package CollectionFramework;
​
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
​
/*
List集合 有序 有下标  可重复
 */
public class TestList {
​
    public static void main(String[] args) {
        //先创建集合对象
        List list = new ArrayList<>();
        //添加
        list.add("苹果");
        list.add("小米");
        list.add(0,"华为");
        System.out.println(list.size());
        System.out.println(list);//[华为, 苹果, 小米]
        //删除
//        list.remove(0);
//        System.out.println(list);//[苹果, 小米]
//        list.remove("苹果");
//        System.out.println(list);//[小米]
​
        //遍历
        //1
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        //2
        System.out.println("=========");
        for (Object o : list) {
            System.out.println(o);
        }
        //3迭代器
        System.out.println("=========");
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //4列表迭代器
        /*
        可以逆向迭代  可以向前或向后  可以删除,添加 修改
         */
        ListIterator listIterator = list.listIterator();
        System.out.println("=========");
        //从前向后
        while (listIterator.hasNext()){//这里下标从0开始
            System.out.println(listIterator.nextIndex()+":"+listIterator.next());
        }
        System.out.println("=========");
        //从后向前
        while (listIterator.hasPrevious()){//这里下标以0结束
            System.out.println(listIterator.previousIndex()+":"+listIterator.previous());
        }
​
        //判断
        System.out.println(list.contains("苹果"));
        System.out.println(list.isEmpty());
​
        //获取位置
        System.out.println(list.indexOf("华为"));
​
    }
​
}
​
package CollectionFramework;
​
import java.util.ArrayList;
import java.util.List;
​
public class TestList02 {
​
    public static void main(String[] args) {
        List list = new ArrayList();
        //因为集合不能存储基本类型  下面隐含了自动装箱
        list.add(20);
        list.add(30);
        list.add(40);
        list.add(50);
        list.add(60);
        System.out.println(list.size());
        System.out.println(list);//[20, 30, 40, 50, 60]
        //删除
//        list.remove("20");//无法删除20  两者类型不一样
//        list.remove(20);//无法删除20  这里会当成下标去执行
//        list.remove((Object) 20);//正确删除  转为Object类型
//        list.remove(new Integer(30));//正确删除 转为Integer
//        list.remove((Integer)40);//正确删除 转为Integer  最好使用上面的new一个
//        System.out.println(list);
​
        //补充subList 返回子集合
        List list1 = list.subList(1, 3);//左闭右开
        System.out.println(list1);//[30, 40]
    }
​
}
​

List的实现类

ArrayList类 重点

  • 数组结构实现 查询快 增删慢

  • JDK1.2版本加入的 运行效率快 线程不安全

  • 源码分析:

    • 默认容量大小为10,这个默认容量是添加了元素 如果没有添加任何元素 默认容量为0 每次扩容为原先的1.5倍

    • elementData数组 存放元素

    • size 实际的元素个数

    • add方法源码分析:

    • public boolean add(E e) {
              ensureCapacityInternal(size + 1);  // Increments modCount!!
              elementData[size++] = e;
              return true;
          }
      private static int calculateCapacity(Object[] elementData, int minCapacity) {
              if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                  return Math.max(DEFAULT_CAPACITY, minCapacity);
              }
              return minCapacity;
          }
      private void ensureExplicitCapacity(int minCapacity) {
              modCount++;
      ​
              // overflow-conscious code
              if (minCapacity - elementData.length > 0)
                  grow(minCapacity);
          }
      //扩容 默认容量为10 当添加第11个时 扩容 每次扩容为原先的1.5倍
        private void grow(int minCapacity) {
              // overflow-conscious code
              int oldCapacity = elementData.length;
              int newCapacity = oldCapacity + (oldCapacity >> 1);
              if (newCapacity - minCapacity < 0)
                  newCapacity = minCapacity;
              if (newCapacity - MAX_ARRAY_SIZE > 0)
                  newCapacity = hugeCapacity(minCapacity);
              // minCapacity is usually close to size, so this is a win:
              elementData = Arrays.copyOf(elementData, newCapacity);
          }

      使用:

      package CollectionFramework;
      ​
      import java.util.ArrayList;
      import java.util.Iterator;
      import java.util.ListIterator;
      ​
      /*
      ArrayList:
      存储结构 :数组  查找快 增删慢
       */
      public class TestArrayList {
      ​
          public static void main(String[] args) {
              ArrayList arrayList = new ArrayList<>();
              //添加
              Student student1 = new Student("刘一",21);
              Student student2 = new Student("刘二",22);
              Student student3 = new Student("刘三",23);
              arrayList.add(student1);
              arrayList.add(student2);
              arrayList.add(student3);
              System.out.println(arrayList.size());
              System.out.println(arrayList);
              //删除
      //        arrayList.remove(student1);
      //        arrayList.remove(new Student("刘二",22));//这样无法删除  解决这个问题  重写equals方法
              /*
                    @Override
                      public boolean equals(Object obj) {
                          if (this==obj){
                          return true;
                          }
                          if (obj==null){
                          return false;
                          }
                          if (obj instanceof Student){
                          Student s = (Student) obj;
                           //比较属性
                          if (this.name.equals(s.getName())&&this.age==s.age){
                          return true;
                          }
                      }
      ​
                      return false;
                  }
               */
              System.out.println(arrayList);
              //遍历
              //迭代器
              Iterator iterator = arrayList.iterator();
              while (iterator.hasNext()){
                  Student s = (Student) iterator.next();
                  System.out.println(s);
              }
              //列表迭代器
              ListIterator listIterator = arrayList.listIterator();
              System.out.println("==========前向后迭代");
              while (listIterator.hasNext()){//这里的下标才1开始
                  Student s2 = (Student) listIterator.next();
                  System.out.println(s2);
              }
              System.out.println("==========后向前迭代");
              while (listIterator.hasPrevious()){//这里的下标从-1开始
                  Student s3 = (Student) listIterator.previous();
                  System.out.println(s3);
              }
              //判断
              //查找
          }
      ​
      }
      ​

Vector类

  • 数组结构 查询快 增删慢

  • JDK1.0版本的 运行效率慢 线程安全 现在已经基本不使用了

  • package CollectionFramework;
    ​
    import java.util.Enumeration;
    import java.util.Vector;
    ​
    /*
    测试Vector类
     */
    public class TestVector {
    ​
        public static void main(String[] args) {
            Vector vector = new Vector<>();
    ​
            vector.add("草莓");
            vector.add("西瓜");
            vector.add("葡萄");
            System.out.println(vector.size());
            System.out.println(vector);
    ​
    //        vector.remove(0);
    //        vector.remove("西瓜");
    //        System.out.println(vector);
    //        vector.clear();
    //        System.out.println(vector);
            //遍历
            //枚举器
            Enumeration elements = vector.elements();
            while (elements.hasMoreElements()){
                String s = (String) elements.nextElement();
                System.out.println(s);
            }
    ​
            //判断
            System.out.println(vector.contains("西瓜"));
            System.out.println(vector.isEmpty());
    ​
            //补充
            System.out.println(vector.lastElement());//最后一个
            System.out.println(vector.firstElement());//第一个
            System.out.println(vector.elementAt(1));//下标为1的
    ​
    ​
        }
    ​
    }
    ​

LinkedList类:

  • 链表结构实现 增删快 查询慢 双向链表

  • package CollectionFramework;
    ​
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.ListIterator;
    ​
    /**
     * 测试 LinkedList  双向链表结构
     */
    public class TestLinkedList {
    ​
        public static void main(String[] args) {
            LinkedList linkedList = new LinkedList<>();
            Student student1 = new Student("宋一",21);
            Student student2 = new Student("宋二",22);
            Student student3 = new Student("宋三",23);
    ​
            linkedList.add(student1);
            linkedList.add(student2);
            linkedList.add(student3);
            System.out.println(linkedList.size());
            System.out.println(linkedList);
    ​
    //        linkedList.remove(student1);
    //        linkedList.remove(new Student("宋二",22));//这里可以删除  因为重写了equals方法在Student类中
    //        System.out.println(linkedList);
    ​
            //遍历
            System.out.println("==============遍历");
            for (int i = 0; i < linkedList.size(); i++) {
                System.out.println(i);
                System.out.println(linkedList.get(i));
            }
            System.out.println("==============遍历");
            for (Object o : linkedList) {
                Student s = (Student) o;
                System.out.println(s);
            }
            System.out.println("==============迭代器");
            Iterator iterator = linkedList.iterator();
            while (iterator.hasNext()){
                System.out.println(iterator.next());
            }
            System.out.println("==============迭代器2");
            ListIterator listIterator = linkedList.listIterator();
            System.out.println("==============前到后");
            while (listIterator.hasNext()){
                Student s2 = (Student)listIterator.next();
                System.out.println("    "+s2+"下标"+listIterator.nextIndex());
            }
            System.out.println("==============后到前");
            while (listIterator.hasPrevious()){
                System.out.println(listIterator.previous()+"下标"+listIterator.previousIndex());
            }
        }
    ​
    }
    ​

泛型

JDK1.5 引入的新特性 其本质是参数化类型 把参数作为参数传递

常见形式:泛型类 泛型接口 泛型方法

语法: <T,.........> T为类型占位符 表示一种引用类型

好处:提高代码的重用性 防止类型转换异常 提高代码安全性

泛型类

package Generic;
​
/*
测试泛型类
语法:在类名后面添加<T,Y,......> T数据类型占位符  引用类型  可以写多个 逗号隔开
 */
public class MyGeneric<T> {
​
    //使用泛型T
    //1创建变量
    T t;
    //2添加为方法参数
    public void show(T t){
//        T t1 = new T();T可以创建变量 但不能new对象 因为类型不知道无法保证构造方法可以使用
        System.out.println(t);
    }
    //3泛型作为方法的返回值
    public T getT(){
        return t;
    }
}
​
//使用
package Generic;
​
public class TestGeneric {
    public static void main(String[] args) {
        //使用泛型类创建对象
        //注意:泛型只能是引用类型  不同的泛型对象不能相互赋值
        MyGeneric<String> myGeneric = new MyGeneric<String>();//后面这个String在JDK1.7后面可以不写
        myGeneric.t="hello";
        myGeneric.show("大家好");
        String string = myGeneric.getT();
​
        MyGeneric<Integer> myGeneric1 = new MyGeneric<>();
        myGeneric1.t=100;
        myGeneric1.show(200);
        Integer integer = myGeneric1.getT();
    }
}
​

泛型接口

使用方法:

  1. 先创建一个泛型接口

    1. package Generic;
      ​
      /**
       * 泛型接口;
       * 语法: 接口名<T>
       *     不能创建泛型静态常量
       */
      public interface MyInterface<T> {
      ​
          String name = "张三";
      ​
          T server(T t);
      ​
      ​
      }
      ​
  2. 创建泛型接口的实现类 有两种方法

    1. 实现类中已经确定泛型的类型

      1. package Generic;
        //在实现接口时  就要把类型确定
        public class MyInterfaceImpl implements MyInterface<String>{
            @Override
            public String server(String s) {
                System.out.println(s);
                return null;
            }
        }
        ​
      2. //在main方法中的使用       
                MyInterfaceImpl impl = new MyInterfaceImpl();
                impl.server("xxxx");
    2. 实现类中没有确定泛型的类型 而是把实现类也写成泛型类 在创建对象的时候 确定类型

      1. package Generic;
        //在实现泛型接口时 还没有确定类型  就把这个类也改成泛型类  创建对象的时候在确定
        public class MyInterfaceImpl02<T> implements MyInterface<T>{
            @Override
            public T server(T t) {
                System.out.println(t);
                return null;
            }
        }
        ​
      2.         MyInterfaceImpl02<Integer> impl02 = new MyInterfaceImpl02();
                impl02.server(1000);

泛型方法

创建泛型方法

package Generic;
​
/**
 * 泛型方法
 * 语法:<T>  方法的返回值类型
 */
public class MyGenericMethod {
​
​
    //泛型方法  T返回值  可以是void 这些
    public <T> T show(T t){
        System.out.println("泛型方法"+t);
        return t;
    }
}
​

调用:

//泛型方法调用
        MyGenericMethod method = new MyGenericMethod();
        method.show("xxxxxxx");//根据你放进去的数据类型自动确定泛型的类型
        method.show(200);

泛型集合

概念:参数化类型 类型安全的集合 强制集合元素的类型必须一致

特点:

  • 编译时就可以检查 而非运行时抛出异常

  • 访问时 不必类型装换(拆箱

  • 不同的泛型之间引用不能相互赋值 泛型不存在多态

package Generic;
​
import CollectionFramework.Student;
​
import java.util.ArrayList;
import java.util.Iterator;
​
public class Demo {
    public static void main(String[] args) {
        //这里没有使用泛型  自动默认都是Object类型
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("xxx");
        arrayList.add("yyy");
//        arrayList.add(10);
//        arrayList.add(20);  这里确定了泛型为String  现在就是String类型的集合  此时集合只能保存String类型
​
//        for (Object o : arrayList) {
//            /*
//            因为没有使用泛型 确定集合中应该只存在该类型的
//            所以默认的是Object类型
//            如果我们需要对数据进行强制转换 很有可能两者无法强转  抛出异常
//            java.lang.Integer cannot be cast to java.lang.String
//             */
            String str = (String) o;//会有类型转换异常 如果没有确定泛型
            System.out.println(str);
//        }
        for (String s : arrayList) {
            System.out.println(s);
        }
​
        ArrayList<Student> arrayList1 = new ArrayList<Student>();
        Student student1 = new Student("x",21);
        Student student2 = new Student("x",21);
        Student student3 = new Student("x",21);
        arrayList1.add(student1);//此时只能添加Student类型的
        arrayList1.add(student2);
        arrayList1.add(student3);
​
        Iterator<Student> iterator = arrayList1.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());//这里next获取的就是Student类型
        }
    }
}
​

Set集合

特点:无效 无下标 不可重复元素

方法全部继承自Collection

set接口的使用

package Generic;
​
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
​
/*
测试Set接口
无序 无下标  不可重复
 */
public class TestSetInterface {
​
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        //添加属性
        set.add("苹果");
        set.add("华为");
        set.add("华为");
        set.add("小米");
        System.out.println(set.size());
        System.out.println(set);
        //删除
//        set.remove("苹果");
//        System.out.println(set);
//        set.clear();
​
        //遍历  两种方式
        //增强for
        System.out.println("=================");
        for (String s : set) {
            System.out.println(s);
        }
        System.out.println("=================");
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        
        //判断
        System.out.println(set.contains("华为"));
        System.out.println(set.isEmpty());
    }
​
}
​

Set的实现类:

HashSet(重点

  • 基于HashCode实现元素不可重复

  • 当存入元素的哈希码相同时,会调用equals进行确认 如果结果为true 则拒绝后者存入

  • //idea可以使用alt加insert快捷键重写
    //自己重写:
        @Override
        public int hashCode() {
            int n1 = this.name.hashCode();
            int n2 = this.age;
    ​
            return n1+n2;
        }
    ​
        @Override
        public boolean equals(Object obj) {
            if (this==obj){
                return true;
            }
            if (obj==null){
                return false;
            }
            if (obj instanceof Person){
                Person p = (Person) obj;
                if (this.name.equals(p.getName())&&this.age==p.getAge()){
                    return true;
                }
            }
            return false;
        }
    //快捷键生成:
    @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Person person = (Person) o;
            return age == person.age && Objects.equals(name, person.name);
        }
    ​
        @Override
        public int hashCode() {
            return Objects.hash(name, age);
        }
  • package Generic;
    ​
    import java.util.HashSet;
    import java.util.Iterator;
    ​
    /**
     * HashSet 的使用
     * 复杂一点的使用
     */
    public class TestHashSet02 {
        public static void main(String[] args) {
            HashSet<Person> hashSet = new HashSet<>();
    ​
            Person person1 = new Person("刘一", 21);
            Person person2 = new Person("刘二", 22);
            Person person3 = new Person("刘三", 23);
            hashSet.add(person1);
            hashSet.add(person2);
            hashSet.add(person3);
            /*
            这个添加是可以成功的 这个new是一个新的对象和person1不一样
            原因:存储过程
            1)根据hashcode计算保存的位置  如果位置为空 则直接保存  不为空执行第二步
            2)再执行equals方法  如果equals方法为true 则认为是重复  否则形成链表
            解决方法重写equals方法 和hashcode方法
        @Override
        public int hashCode() {
            int n1 = this.name.hashCode();
            int n2 = this.age;
    ​
            return n1+n2;
        }
    ​
        @Override
        public boolean equals(Object obj) {
            if (this==obj){
                return true;
            }
            if (obj==null){
                return false;
            }
            if (obj instanceof Person){
                Person p = (Person) obj;
                if (this.name.equals(p.getName())&&this.age==p.getAge()){
                    return true;
                }
            }
            return false;
        }
             */
            hashSet.add(new Person("刘一", 21));//这个添加是可以成功的 这个new是一个新的对象和person1不一样  解决方法重写equals方法和hashcode方法
    ​
            System.out.println(hashSet.size());
            System.out.println(hashSet);
    ​
            //删除
    //        hashSet.remove(person1);
    //        hashSet.remove(new Person("刘二", 22));//在equals方法和hashcode方法重写前删不了  现在可以
    //        System.out.println(hashSet);
    ​
            //遍历  两种
            for (Person person : hashSet) {
                System.out.println(person);
            }
            System.out.println("=====迭代器========");
            Iterator<Person> iterator = hashSet.iterator();
            while (iterator.hasNext()){
                System.out.println(iterator.next());
            }
    ​
            //判断
            System.out.println(hashSet.contains(new Person("刘一", 21)));//因为重写了equals方法和hashcode方法 所以可以这样判断
            System.out.println(hashSet.isEmpty());
        }
    }
    ​
  • package Generic;
    ​
    import java.util.HashSet;
    import java.util.Iterator;
    ​
    /*
    HashSet集合的使用
    存储结构  哈希表(数组+链表+红黑树)
     */
    public class TestHashSet {
    ​
        public static void main(String[] args) {
            //新建集合
            HashSet<String> hashSet = new HashSet<>();
            //添加
            hashSet.add("刘一");
            hashSet.add("刘二");
            hashSet.add("刘三");
            hashSet.add("刘四");
            hashSet.add("刘四");
    ​
            System.out.println(hashSet.size());
            System.out.println(hashSet);
    ​
            //删除
            hashSet.remove("刘四");
            System.out.println(hashSet);
    ​
            //遍历  两种
            for (String s : hashSet) {
                System.out.println(s);
            }
            System.out.println("============");
            Iterator<String> iterator = hashSet.iterator();
            while (iterator.hasNext()){
                System.out.println(iterator.next());
            }
    ​
            //判断
            System.out.println(hashSet.contains("刘一"));
            System.out.println(hashSet.isEmpty());
        }
    ​
    }
    ​

TreeSet

  • 基于排列顺序实现元素不重复 二叉树 红黑树(平衡二叉树)

  • 实现SortedSet接口 对集合元素自动排序

  • 元素对象的类型必须实现Comparable接口 指定排序顺序

  • Comparator接口的使用 定制比较(比较器)* 使用比较器后 集合了的元素可以不用实现Comparable接口

  • 通过CompareTo方法确定是否是重复元素

  • 简单使用:

    • package Generic;
      ​
      import java.util.Iterator;
      import java.util.TreeSet;
      ​
      /**
       * TreeSet集合的使用
       * 存储结构:红黑树
       */
      public class TestTreeSet {
      ​
          public static void main(String[] args) {
              TreeSet<String> treeSet = new TreeSet<>();
              treeSet.add("xyz");
              treeSet.add("abc");
              treeSet.add("hello");
              System.out.println(treeSet.size());
              System.out.println(treeSet);//[abc, hello, xyz]
      ​
      //        treeSet.remove("xyz");
      //        System.out.println(treeSet);
      ​
              //遍历
              for (String s : treeSet) {
                  System.out.println(s);
              }
              Iterator<String> iterator = treeSet.iterator();
              while (iterator.hasNext()){
                  System.out.println(iterator.next());
              }
      ​
              //判断
              System.out.println(treeSet.contains("abc"));
              System.out.println(treeSet.isEmpty());
          }
      ​
      }
      ​
  • package Generic;
    ​
    import java.util.Iterator;
    import java.util.TreeSet;
    ​
    /**
     * TreeSet集合
     * 要求集合元素必须实现Comparable接口
     */
    public class TestTreeSet02 {
    ​
        public static void main(String[] args) {
            TreeSet<Person> treeSet = new TreeSet<>();
            /*
            异常:java.lang.ClassCastException
            Generic.Person cannot be cast to java.lang.Comparable
            因为Person没有实现Comparable接口 CompareTo方法的返回值为0 认为是重复元素
            重写比较规则
            //比较规则
        @Override
        public int compareTo(Person o) {
            int n1 = this.getName().compareTo(o.getName());
            int n2 = this.age - o.getAge();
            return n1==0?n2:n1;
        }
             */
            Person person1 = new Person("刘一", 21);
            Person person2 = new Person("刘二", 22);
            Person person3 = new Person("刘三", 23);
            treeSet.add(person1);
            treeSet.add(person2);
            treeSet.add(person3);
            System.out.println(treeSet.size());
            System.out.println(treeSet);
    ​
    //        treeSet.remove(person1);
    //        treeSet.remove(new Person("刘三", 23));//这样可以删除 因为实现CompareTo方法里面是通过比较名字和年龄
    //        System.out.println(treeSet);
    ​
            //遍历
            for (Person person : treeSet) {
                System.out.println(person);
            }
            System.out.println("===========");
            Iterator<Person> iterator = treeSet.iterator();
            while (iterator.hasNext()){
                System.out.println(iterator.next());
            }
    ​
            //判断
            System.out.println(treeSet.contains(person1));
            System.out.println(treeSet.contains(new Person("刘三", 23)));
            System.out.println(treeSet.isEmpty());
        }
    ​
    }
    ​

补充Comparator接口:

  • package Generic;
    ​
    import java.util.Comparator;
    import java.util.TreeSet;
    ​
    /**
     * TreeSet集合
     * Comparator接口的使用  定制比较(比较器)
     * 使用比较器后  集合了的元素可以不用实现Comparable接口
     */
    public class TestTreeSet03 {
    ​
        public static void main(String[] args) {
            //创建集合并指定比较规则
            TreeSet<Person> treeSet = new TreeSet<>(new Comparator<Person>() {
                @Override
                public int compare(Person o1, Person o2) {
                    int n1 = o1.getAge()-o2.getAge();
                    int n2 = o1.getName().compareTo(o2.getName());
                    return n1==0?n2:n1;
                }
            });
            Person person1 = new Person("刘一", 21);
            Person person2 = new Person("刘二", 22);
            Person person3 = new Person("刘三", 23);
            Person person4 = new Person("刘三三", 23);
            treeSet.add(person1);
            treeSet.add(person2);
            treeSet.add(person3);
            treeSet.add(person4);
            System.out.println(treeSet);
    ​
        }
    ​
    }
    ​
  • TreeSet案例:

    • package Generic;
      ​
      import java.util.Comparator;
      import java.util.TreeSet;
      ​
      /**
       * 要求 使用TreeSet集合按照字符串长度进行排序
       */
      public class TestTreeSet04 {
      ​
          public static void main(String[] args) {
              TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
                  @Override
                  public int compare(String o1, String o2) {
                      int n1=o1.length()-o2.length();
                      int n2=o1.compareTo(o2);//原来的比较规则
                      return n1==0?n2:n1;
                  }
              });
      ​
              treeSet.add("hello");
              treeSet.add("hello world");
              treeSet.add("apple");
              treeSet.add("songhongming");
              treeSet.add("jiang");
              treeSet.add("cat");
              System.out.println(treeSet);
          }
      ​
      }
      ​

Map体系集合

特点:

  • 用于存储任意键值对

  • 键 无序 无下标 不允许重复

  • 值 无序 无下标 可以重复

方法:

  • put(K key,V value) 将对象存入到集合中 关联键值 key重复则覆盖原值

  • get(Object key) 获取key对应的值

  • Set<K> keySet() 返回所有的key

  • Collection<V> values() 返回所有值的Collection集合

  • Set<Map.Entry<K,V>> 键值匹配的Set集合

Map接口的使用:

基本使用:

package Generic;
​
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
​
/**
 * Map接口的使用
 * 存储键值对  键不能重复  值可以重复  无序
 */
public class TestMap {
​
    public static void main(String[] args) {
        //创建Map集合  两个String设置键  值的 类型  因为Map是一个接口 所以需要new他的实现类 HashMap
        Map<String, String> map = new HashMap<>();
        //添加元素
        map.put("cn","中国");
        map.put("uk","英国");
        map.put("usa","美国");
​
        System.out.println(map);//{usa=美国, uk=英国, cn=中国}
        System.out.println(map.size());
        System.out.println(map.get("cn"));//中国
        map.put("cn","古代中国");//因为有重复键  所以覆盖原先的值 中国  被覆盖为 古代中国
        System.out.println(map);//{usa=美国, uk=英国, cn=古代中国}
​
        //删除
//        map.remove("usa");
//        System.out.println(map);
​
        //遍历
        //1使用keySet();
        System.out.println("====1使用keySet();=====");
        Set<String> keySet = map.keySet();//得到key的Set集合
        for (String key : keySet) {
            System.out.println(key);//usa uk cn
            System.out.println(map.get(key));//美国 英国  古代中国
        }
        //2.使用entrySet()方法  效率略高于上面
        System.out.println("====2.使用entrySet()方法=====");
        Set<Map.Entry<String, String>> entrySet = map.entrySet();//entry 一个键值对
        for (Map.Entry<String, String> entry : entrySet) {
            System.out.println(entry);//usa=美国  uk=英国 cn=古代中国
            System.out.println(entry.getKey());
            System.out.println(entry.getValue());
        }
​
        //判断
        System.out.println(map.containsKey("cn"));//true
        System.out.println(map.containsValue("泰国"));//false
​
    }
​
}
​

Map集合的实现类

HashMap 重点

特点:

  • JDK1.2 线程不安全 运行效率快 允许用null作为key或者value

  • 无参构造器构造一个具有默认容量(16)和默认加载因子(0.75)(超过容量的75%开始扩容)的空HashMap 每次扩容容量翻倍

    package Generic;
    ​
    import java.util.HashMap;
    import java.util.Map;
    ​
    /**
     * HashMap的使用
     * 存储结构 哈希表
     */
    public class TestHashMap {
    ​
        public static void main(String[] args) {
            //创建集合
            HashMap<Student,String> hashMap = new HashMap<>();
            //添加
            Student student1 = new Student("孙悟空", 100);
            Student student2 = new Student("猪八戒", 110);
            Student student3 = new Student("沙和尚", 111);
    ​
            hashMap.put(student1,"北京");
            hashMap.put(student2,"上海");
            hashMap.put(student3,"杭州");
    //        hashMap.put(student3,"株州");
            System.out.println(hashMap.size());
            System.out.println(hashMap);
            System.out.println(hashMap.get(student1));
    ​
            /*
            下面添加会成功 因为new是一个新的对象 和student3  不一样
            因为是使用key的hashcode的equal方法 来作为重复依据 比得是地址
            解决:重写equals方法和hashcode在Student类中
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Student student = (Student) o;
            return stuNo == student.stuNo && Objects.equals(name, student.name);
        }
    ​
        @Override
        public int hashCode() {
            return Objects.hash(name, stuNo);
        }
             */
            hashMap.put(new Student("沙和尚", 111),"北京");
            System.out.println(hashMap);
    ​
            //删除
    //        hashMap.remove(student3);
    //        System.out.println(hashMap.size());
            //遍历
            //1使用keySet方法
            System.out.println("======1使用keySet方法=====");
            for (Student student : hashMap.keySet()) {
                System.out.println(student);//Student{name='猪八戒', stuNo=110}
                System.out.println(hashMap.get(student));//上海
            }
            //2使用entrySet集合
            System.out.println("======2使用entrySet集合=====");
            for (Map.Entry<Student, String> entry : hashMap.entrySet()) {
                System.out.println(entry);//Student{name='猪八戒', stuNo=110}=上海
                System.out.println(entry.getKey());//Student{name='猪八戒', stuNo=110}
                System.out.println(entry.getValue());//上海
            }
            
            //判断
            System.out.println(hashMap.containsKey(student1));
            System.out.println(hashMap.containsKey(new Student("沙和尚", 111)));//重写方法前判断为false  现在为true
            System.out.println(hashMap.isEmpty());
    ​
        }
    ​
    }
    ​
  • 源码分析:

    • static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 hashMap的初始容量大小16
      static final int MAXIMUM_CAPACITY = 1 << 30;//hashMap数组最大容量
      static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认加载因子
      static final int TREEIFY_THRESHOLD = 8;//当链表长度大于8,调整为红黑树 JDK1.8
      static final int UNTREEIFY_THRESHOLD = 6;//当链表长度小于6 调整为链表 JDK1.8
      static final int MIN_TREEIFY_CAPACITY = 64;//当链表长度大于8时 并且集合元素大于等于64 调整为红黑树JDK1.8
      transient Node<K,V>[] table;//在hashMap刚刚创建没有添加元素时 为null 
      transient int size;//为0
    • 总结:

      • hashMap刚刚创建时 table是null 为了节省空间 当添加了第一个元素 table容量调整为16

      • 当元素个数大于阈值(16*0.75=12)是 进行扩容 扩容为原来两倍 目的减少调整元素的个数

      • JDK1.8 当链表长度大于8时 并且集合元素大于等于64 调整为红黑树 目的提高执行效率

      • 当链表长度小于6 调整为链表 JDK1.8

      • JDK1.8前 链表是头插入 JDK1.8后 链表是尾插入 头插入在多线程的情况下可能有死链

HashTable 了解就行

JDK1.0 线程安全 运行效率慢 不允许null作为key或者value

默认初始容量11 加载因子0.75

子类Properties使用比较多

要求key和value都是String 通常用于配置文件的读取 与流联系紧密

TreeMap:

存储结构 红黑树

实现SortedMap接口(Map的子接口),可以对key自动排序

package Generic;
​
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
​
/**
 * TreeMap的使用
 */
public class TestTreeMap {
​
    public static void main(String[] args) {
        TreeMap<Student, String> treeMap = new TreeMap<>();
        Student student1 = new Student("孙悟空", 1001);
        Student student2 = new Student("猪八戒", 1002);
        Student student3 = new Student("沙和尚", 1003);
​
        /*
        报错:
        java.lang.ClassCastException: Generic.Student cannot be cast to java.lang.Comparable
        因为Student没有实现Comparable接口 需要实现Comparable接口  重写CompareTo方法 怎么比较
        @Override
    public int compareTo(Student o) {
        int n2 = this.stuNo-o.getStuNo();
        //只比较学号
        return n2;
    }
        或者使用比较器
         */
        treeMap.put(student1,"北京");
        treeMap.put(student2,"上海");
        treeMap.put(student3,"南昌");
        System.out.println(treeMap.size());
        System.out.println(treeMap);
        
        //遍历
        //1.使用keySet
        for (Student student : treeMap.keySet()) {
            System.out.println(student+""+treeMap.get(student));
        }
        //使用entrySet
        Set<Map.Entry<Student, String>> entrySet = treeMap.entrySet();
        for (Map.Entry<Student, String> entry : entrySet) {
            System.out.println(entry);
            System.out.println(entry.getValue());
            System.out.println(entry.getKey());
        }
        //判断
        System.out.println(treeMap.containsKey(student1));
​
    }
​
}
​

Collection工具类

j集合工具类 定义了除了存取以外的集合常用方法

reverse 反转集合中元素顺序

shuffle 随机重置集合元素顺序

sort 升序排序

package CollectionFramework;
​
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
​
/**
 * 演示Collections 工具类的使用
 */
public class TestCollectionClass {
​
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(20);
        list.add(2);
        list.add(10);
        list.add(12);
        list.add(25);
        list.add(8);
        //sort升序排序
        System.out.println("排序前"+list);
        Collections.sort(list);
        System.out.println("排序后"+list);
        //二分查找  binarySearch  必须先排序
        int i = Collections.binarySearch(list, 12);
        System.out.println(i);//3
​
        //copy复制
        ArrayList<Integer> dest = new ArrayList<>();
        /*
        Collections.copy(dest,list);报错
        java.lang.IndexOutOfBoundsException: Source does not fit in dest
        这个方法要求双方的大小一致 否则报错
​
         */
        for (int j = 0; j < list.size(); j++) {
            dest.add(0);//解决方法
        }
        Collections.copy(dest,list);
        System.out.println(dest);
​
​
//        reverse 反转
        Collections.reverse(list);
        System.out.println(list);
​
        //shuffle  打乱
        Collections.shuffle(list);
        System.out.println(list);
​
        //补充
        //List转成数组
        Integer[] integers = list.toArray(new Integer[0]);
        System.out.println(integers.length);
        System.out.println(Arrays.toString(integers));
        //数组变集合
        String[] names = {"张三","李四","王五"};
        //这个集合是受限集合  无法添加删除
        List<String> list1 = Arrays.asList(names);
        System.out.println(list1);
        
        int[] nums = {100,200,300,400,500};
        List<int[]> ints = Arrays.asList(nums);//基本数据类型转集合 《》里面只能写对应的基本类型 不能写包装类
​
    }
​
}
​

集合总结:

TreeSet TreeMap 两个集合添加的对象 必须实现 Comparable 接口重写CompareTo方法 或者实现比较器

比较器:

TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //int n1=o1.length()-o2.length();
                //int n2=o1.compareTo(o2);//原来的比较规则
                //return n1==0?n2:n1;
                //里面写比较规则
            }
        });

List集合 有序 有下标 元素可以重复

  • ArrayList 数组实现 查询快 增删慢 JDK1.2版本加入的 运行效率快 线程不安全

  • Vector 数组结构 查询快 增删慢JDK1.0版本的 运行效率慢 线程安全 现在已经基本不使用了

  • LinkedList 链表结构实现 增删快 查询慢 双向链表

Set集合 无序 无下标 元素不可重复

  • HashSet 基于HashCode实现元素不可重复当存入元素的哈希码相同时,会调用equals进行确认 如果结果为true 则拒绝后者存入

  • TreeSet

    • 基于排列顺序实现元素不重复 二叉树 红黑树(平衡二叉树)

    • 实现SortedSet接口 对集合元素自动排序

    • 元素对象的类型必须实现Comparable接口 指定排序顺序

    • Comparator接口的使用 定制比较(比较器)* 使用比较器后 集合了的元素可以不用实现Comparable接口

    • 通过CompareTo方法确定是否是重复元素

Map集合 存储一对数据 无序 无下标 键不可重复 值可以 重复 哈希表结构

  • HashMap JDK1.2 线程不安全 运行效率快 允许用null作为key或者value

  • HashTable JDK1.0 线程安全 运行效率慢 不允许null作为key或者value

  • TreeMap 存储结构 红黑树实现SortedMap接口(Map的子接口),可以对key自动排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值