集合的笔记

 

集合:是一个大小可变的容器。


集合与数组的区别:
   
  数组的长度是定义出来就固定的,数组的存储的数据类型也固定了。
     集合的大小可变,可以存储任意类型的数据。
     容器中的数据也称为元素。
     开发中:集合用的更多。原因是集合的大小可变,开发中的数据通常是变化的。

 Java中集合的代表是Collection。

Java中集合的体系结构:
     
集合不只有一种,集合有很多个,每个集合的功能是存在差异的。


                              Collection<E>(接口,不能直接使用)
                                           /                                   \
                       Set<E>(接口)                              List<E>(接口)
                                       /                                     /                         \
                   HashSet<E>(实现类)      ArrayList<E>(实现类)     LinkedList<E>(实现类)
                                /
LinkedHashSet<E>(实现类)

Collection体系集合的特点:


    Set系列集合的特点:添加的元素是无序,不重复的,无索引。

    Set集合无序的根本原因就是用了哈希表存储元素
         -- HashSet:添加的元素是无序不重复的无索引。
         -- LinkedHashSet:添加的元素是有序不重复的。
    List系列集合的特点: 添加的元素是有序,可重复,有索引。
         -- ArrayList: 添加的元素是有序,可重复,有索引。
         -- LinkedList: 添加的元素是有序,可重复,有索引。

                                                              Collections工具类的使用:
    Arrays不是数组,是操作数组的
   Collections不是集合,是操作集合的。
    工具类的方法基本上都是静态的。

 Collections静态方法:
   (1)public static <T> boolean addAll(Collection<T> c , T... elements)
      给集合添加元素。
      支持所有集合的。
      参数一:支持所有集合
      参数二:支持加入可变参数的数据。

  (2)public static void shuffle(List<?> list)
      将集合中的元素乱序。
     参数:是一个List集合
    这个方法只能支持List集合

   (3)public static <T> void sort(List<T> list)
      将集合中的元素排序,默认是升序排序
      参数:是一个List集合
      这个方法只能支持List集合的排序
      排序:大小顺序。
      有序:添加顺序。

(4)public static <T> void sort(List<T> list, Comparator<? super T> c)
        参数一:需要被排序的集合
        参数二:自定义比较规则对象:比较器。

    注意:对于数值类型的集合sort方法可以直接自动的升序排序。
        对于引用数据类型,sort不能排序,原因是人家根本不清楚大小规则。

public class CollectionsDemo02 {
    public static void main(String[] args) {
        List<Apple> apples = new ArrayList<>();
        apples.add(new Apple("红富士1","红色",502.29));
        apples.add(new Apple("红富士2","粉红",602.29));
        apples.add(new Apple("水晶","绿色",303.8));
        // Collections集合默认不能为对象排序的,原因是人家根本不清楚大小规则。
        // Collections.sort(apples);

        // Collections集合提供了一个排序方法。
        // (4)public static <T> void sort(List<T> list, Comparator<? super T> c)
        // 我们认为应该按照重量比较。
        Collections.sort(apples, new Comparator<Apple>() {
            @Override
            public int compare(Apple o1, Apple o2) {
                // 比较方法:
                // 默认会自动提取集合中的两个两个对象,拿来给程序员自己比较
                // 如果程序员认为o1比o2大应该返回一个正整数即可。
                // 如果程序员认为o1比o2小应该返回一个负整数即可。
                // 如果程序员认为o1等于o2应该返回0。
                // o1 = a1
                // o2 = a2
                if(o1.getWeight() > o2.getWeight()){
                    return 1 ; // 大于
                }else if(o1.getWeight() < o2.getWeight()){
                    return -1 ; // 小于
                }
                return 0; // 相等了
            }
        });

        System.out.println(apples);
    }
}
List<String> lists1 = new ArrayList<>();
Collections.addAll(lists1,"张三","李四","王五","王麻子");
Collections.shuffle(lists1); // 打乱顺序 :洗牌
System.out.println(lists1);
List<Integer> lists2 = new ArrayList<>();
lists2.add(12);
lists2.add(12);
lists2.add(5);
lists2.add(19);
lists2.add(19);
lists2.add(111);
lists2.add(89);
Collections.sort(lists2); // 排序!
System.out.println(lists2);

 

LinkedList集合:

底层是双链表结构,”查询慢“,”增删快“,线程不安全的,效率高

有序(存取顺序一致),有索引,元素可重复

LinkedList集合是可以用来设计队列和栈的。
如果需要执行大量的增删操作,则选择LinkedList。
如果不需要执行增删操作,而存在查询操作,则选择ArrayList

LinkedList集合特有方法方法:
   因为双链表结构,首尾元素是可以直接定位的。
   所以LinkedList集合操作首位元素的性能极好,所以
   LinkedList集合提供了很多的首位操作的API:

   public void addFirst(E e):  将元素添加到链表头
    public void addLast(E e):   将元素添加到链表尾部
    public E getFirst():         获得链表头元素
    public E getLast():          获得链表尾部元素
    public E removeFirst():      删除链表头元素
    public E removeLast():       删除链表尾部元素

   LinkedList集合是可以用来设计队列和栈的。

   1,// 添加的元素是有序,可重复,有索引。
Collection lists = new ArrayList();
lists.add("java1");
lists.add("java1");
lists.add("java2");
lists.add("java2");
System.out.println(lists);

打印    [java1, java1, java2, java2]

2,// HashSet : 添加的元素是无序,不重复的,无索引。
Collection c = new HashSet();
c.add("xiaoPang");
c.add("Java");
c.add("Java");
c.add("JavaEE");
c.add("JavaEE");
c.add("Oracle");
System.out.println(c);

打印     [Java, JavaEE, xiaoPang, Oracle]

 

Collection接口是全部集合的父类。Collection集合的功能是所有集合通用的。

Collection集合的常用API有哪些呢?
     public boolean add(E e)`:  把给定的对象添加到当前集合中 。
     public void clear()` :清空集合中所有的元素。
     public boolean remove(E e)`: 把给定的对象在当前集合中删除。
     public boolean contains(Object obj)`: 判断当前集合中是否包含给定的对象。
     public boolean isEmpty()`: 判断当前集合是否为空。
     public int size()`: 返回集合中元素的个数。
     public Object[] toArray()`: 把集合中的元素,存储到数组中
Collection c1 = new ArrayList();
/ 获取集合元素的大小!
System.out.println(c1.size());

// 把集合转换成数组:集合一旦元素确定了就可以转成数组。

Object[] arrs = c1.toArray();
System.out.println("数组:"+Arrays.toString(arrs));
Collection集合的遍历:
   有三种的:
     (1)foreach遍历是可以的。
           for(被遍历集合或者数组中元素的类型  变量 :  被遍历集合或者数组){

           }
     (2)迭代器


     (3)JDK 1.8之后的新技术
Collection<String> c = new ArrayList<>();
c.add("JavaEE");
c.add("Oracle");
c.add("Mysql");
c.add("Redis");
System.out.println(c);

// JDK 1.8之后的新技术(暂时了解): Lambda表达式遍历集合。
c.forEach( s -> {
    System.out.println(s);
});

System.out.println("-------------");
c.forEach( s -> System.out.println(s)  );

System.out.println("-------------");
c.forEach(System.out::println );

 

泛型在集合中的使用。

泛型的概念:是用于约束某个类只能操作某个数据类型。
泛型的格式: <数据类型> ,泛型可以理解成标记。

Collection集合是全部支持泛型的。
泛型中的数据类型只能是引用数据类型。集合也只能支持引用数据类型。
不能填写int  byte而应该是Integer , Byte

泛型好处:可读性好,约定集合只能存储某个类型,避免数据类型转换异常ClassCastException。

1.集合使用了什么泛型就只能支持什么数据类型。
2.JDK 1.7之后泛型后面是不用申明数据类型的
  Collection<String> c = new ArrayList<String>();
  Collection<String> c = new ArrayList<>();

定义泛型方法。

需求: 随便给你一个数组,就能输出这个数组的元素内容。

泛型方法的格式:
    修饰符 <泛型变量> 返回值类型 方法名称(形参){

    }
    要求:必须使用<泛型变量>申明。
        前后的泛型变量必须一致!

public class FanXingDemo01 {
    public static void main(String[] args) {
        Integer[] arrs = new Integer[]{10,20,30,40};
        String[] names = new String[]{"李开义","李童洲","李锰"};
        Double[] scores = new Double[]{19.2,22.3 ,33.2};

        printArr(arrs);
        printArr(names);
        printArr(scores);

    }

    public static  <T> void printArr(T[] arrs){
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        // 直接遍历数组输出元素的内容
        for(int i = 0 ; i < arrs.length ; i++){
            T ele = arrs[i];

            sb.append(i==arrs.length -1 ? ele : ele+",");

            /* if(i == arrs.length -1){
                sb.append(ele);
            }else{
                sb.append(ele+",");
            }*/
        }
        sb.append("]");
        System.out.println(sb);
    }
}

泛型接口和使用。

泛型接口的定义:  用了泛型的接口就是泛型接口。
泛型接口的定义格式:
   修饰符 接口名称<泛型变量>{}

class SavaClazz implements Save<Clazz>{
    @Override
    public void add(Clazz stu) {

    }
}

class SaveStudent implements Save<Student>{
    @Override
    public void add(Student stu) {

    }
}

class SavaAnimal implements Save<Animal>{
    @Override
    public void add(Animal stu) {

    }
}

// 公司的规范:保存数据
interface Save<E>{
    void add(E stu);
}

class Student{

}

class Clazz{

}

class Animal{

}

 

 

泛型的通配符。

需求:开发一个极品飞车的游戏。
可能有很多车,每种车可以一起参数比赛。

注意:
   虽然Jeep 继承了 Car
  但是Collection<Jeep>泛型类型和Collection<Car>泛型没有继承关系。

 通配符:就是? 可以在泛型使用数据类型的时候代表一切类型。

 泛型的上下限:可以约束?是什么要求
      ? extends Car : 泛型的上限?必须是Car或者子类。
      ? super Car :   泛型的下限?必须是Car或者父类。(不会用)

public class GameDemo01 {
    public static void main(String[] args) {
        // 创建几部车。
        Collection<BMW> bmws = new ArrayList<>();
        bmws.add(new BMW());
        bmws.add(new BMW());
        bmws.add(new BMW());
        start(bmws);

        Collection<JEEP> jeeps = new ArrayList<>();
        jeeps.add(new JEEP());
        jeeps.add(new JEEP());
        start(jeeps);

//        Collection<Dog> dogs = new ArrayList<>();
//        dogs.add(new Dog());
//        dogs.add(new Dog());
//        start(dogs);

    }

    // 写一个比赛的方法
    public static void start(Collection<? extends Car> cars){

    }

}
class Dog{

}

// 汽车:父类。
class Car{

}

class BMW extends Car{

}

class JEEP extends Car{

}

                                                                     Map集合的概述。
    什么是Map集合?Map集合也是一个容器。与Collection集合是没有关系的,  他们属于两个不同的集合体系。
    Map集合称为键值对集合,Map集合中的每个元素是有两个值组成的   

Map集合的每个元素的格式是:“键=值”      有时候我们称键是key , 值是value.
    所以Map集合的元素格式是:
       {key1=value1 , key2=value2 , key3=value3 , ...}

    小结:有人把Map集合称为双列即可,而Collection集合称为单列集合。

为什么要使用Map集合呢?


       原因1:
          Map集合的信息描述更加的具体和直观。
          需求:存储一个学生的信息(徐干,21 ,男,101期就业班级)。
          Collection存储: [徐干,21 ,男,101期就业班级]
          Map集合存储: {姓名=徐干,年龄=21,性别=男,班级=101期就业班级}

       原因2:
          场景:需要开发一个购物车系统。
          购物车中的信息可以采用Map集合存储:
          Map集合的格式:
          {iphonex=100 , iphoneXMax=1 , Apple=100}

    总结:对于信息需要很具体化,或者类似购物车这样的业务,使用Map集合存储数据
          会更加的合适。

Map集合也存在自己的体系结构。

     Map是Map集合的根类。

     Map<K,V>:接口 , K - 此映射所维护的键的类型 ,  V - 映射值的类型
         /
     HashMap<K,V>: 实现类。可以使用的。
        /
    LinkedHashMap<K,V>: 实现类。可以使用的。

 Map集合体系结构的特点:
    Map系列集合:元素是无序,键是不重复的,值是不做要求的。
               键值对都可以为null。
    HashMap实现类的特点:元素是无序,键是不重复的,值是不做要求的。
           键值对都可以为null。
    LinkedHashMap实现类的特点:元素是有序,键是不重复的,值是不做要求的。
       键值对都可以为null。

 小结:
     1.Map集合的元素是无序的,键是不重复的,值是不做要求的。
     2.如果键重复了,后面键对应的整个元素会覆盖前面重复键对应的整个元素。
     3.Map集合的元素值是不做要求的。
     4.Map集合的键值对都可以为null。
     5.Map集合的键是什么类型,值是什么类型,添加的元素就必须是这些类型。

Map集合的常用方法(API):
    - `public V put(K key, V value)`:  把指定的键与指定的值添加到Map集合中。
    - `public V remove(Object key)`: 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
    - `public V get(Object key)` 根据指定的键,在Map集合中获取对应的值。
    - `public Set<K> keySet()`: 获取Map集合中所有的键,存储到Set集合中。
    - `public boolean containKey(Object key)`:判断该集合中是否有此键。
  小结:
     1.这些API很重要必须记住(理解记忆)
     2.这些API在以后的开发中用的很多!!

 

                                          Map集合的遍历:
   Map集合的遍历是只一个一个元素的取出来(此时包含了每个元素的键和值)。
   Map集合的遍历有3种方式:
   方式一: 键找值,根据先获取Map集合的全部键,再来找到全部的值。

 

 

public class MapDemo01 {
    public static void main(String[] args) {
        // 1.创建一个Map集合对象。
        Map<String,String> maps = new HashMap<>();
        maps.put("徐干","广州");
        maps.put("孙悟空","花果山");
        maps.put("蜘蛛精","盘丝洞");

        // 2.通过调用Map集合的keySet()方法,提取Map集合的全部键,
        // 是放到一个Set集和
        Set<String> keys = maps.keySet();
        //System.out.println(keys);
        // 3.遍历Map集合的全部键。
        for(String key : keys){
           // 4.根据每个键调用get(K key)来获取对应的值。
            String value = maps.get(key);
            System.out.println(key+"="+value);
        }
    }
}

方式一的遍历:
    键找值,根据先获取Map集合的全部键,再来找到全部的值。
    步骤:
       1.创建一个Map集合对象。
       2.通过调用Map集合的keySet()方法,提取Map集合的全部键,是放到一个Set集合。
       3.遍历Map集合的全部键。
       4.根据每个键调用get(K key)来获取对应的值。
    小结:
       这种方式实际上是比较简单的,建议大家使用。

   方法二:键值对方法来遍历。

public class MapDemo02 {
    public static void main(String[] args) {
        // 1.创建一个Map集合对象。
        Map<String,String> maps = new HashMap<>();
        maps.put("徐干","广州");
        maps.put("孙悟空","花果山");
        maps.put("蜘蛛精","盘丝洞");
        System.out.println(maps);

        // maps = {  蜘蛛精=盘丝洞    , 孙悟空=花果山  , 徐干=广州}
        //

        //  使用一种foreach遍历的形式。
        /**
         * foreach格式:
         *    for(被遍历集合或者数组中元素的类型 变量名称 : 被遍历集合或者数组){
         *
         *    }
         *
         * 如果直接对Map集合使用foreach遍历,我们是不清楚Map集合元素(key=value)的类型的。
         * Map集合是不能直接用foreach来遍历的。
         *
         * 所以Java提供了一个方法:Set<Map.Entry<K,V>> entrySet()
         * 可以把Map集合转换成一个Set集合
         * sets = [ (蜘蛛精=盘丝洞)    , (孙悟空=花果山)  , (徐干=广州) ]
         *                                entry
         * 此时这个元素:(蜘蛛精=盘丝洞)就有类型:Map.Entry<String,String>
         *
         */
        Set<Map.Entry<String,String>> sets = maps.entrySet();
        for(Map.Entry<String,String> entry : sets){
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "=" + value);
        }
    }
}

Map集合的遍历方式二:
       键值对方式来遍历。
       是一种foreach遍历的形式。
       Java提供了一个方法:Set<Map.Entry<K,V>> entrySet()
      可以把Map集合转换成一个Set集合
      sets = [ (蜘蛛精=盘丝洞)    , (孙悟空=花果山)  , (徐干=广州) ]
                                entry
      此时这个元素:(蜘蛛精=盘丝洞)就有类型:Map.Entry<String,String>

      小结:
         方式二相对较复杂,大家可以选用!!

   方法三:JDK1.8之后的新技术来遍历(Lambda表达式,现在了解即可)

public class MapDemo03 {
    public static void main(String[] args) {
        Map<String,String> maps = new HashMap<>();
        maps.put("徐干","广州");
        maps.put("孙悟空","花果山");
        maps.put("蜘蛛精","盘丝洞");

        maps.forEach((k , v) -> {
            System.out.println(k + "=" + v);
        });

        // maps.forEach((k , v) ->  System.out.println(k + "=" + v));


    }
}

Map集合也存在自己的体系结构。

      Map是Map集合的根类。

      Map<K,V>:接口 , K - 此映射所维护的键的类型 ,  V - 映射值的类型
        /
    HashMap<K,V>: 实现类。可以使用的。
       /
    LinkedHashMap<K,V>: 实现类。可以使用的。

 Map集合体系结构的特点:
     Map系列集合:元素是无序,键是不重复的,值是不做要求的。
     键值对都可以为null。
     HashMap实现类的特点:元素是无序,键是不重复的,值是不做要求的。
     键值对都可以为null。
     LinkedHashMap实现类的特点:元素是有序,键是不重复的,值是不做要求的。
     键值对都可以为null。

  1.LinkedHashMap实现类的特点:元素是"有序",键是不重复的,值是不做要求的。
      键值对都可以为null。
     LinkedHashMap使用了链表来记录每个元素的添加顺序。所以有序!
 

public class LinkedHashMapDemo01 {
    public static void main(String[] args) {
        Map<String,Integer> maps = new LinkedHashMap<>();
        // 添加一些元素:put
        maps.put("iphoneX",1); // 被覆盖
        maps.put("iphoneX",100);
        maps.put("iphoneMax",100); // 被覆盖
        maps.put("iphoneMax",1);
        maps.put("apple",100);
        maps.put(null,null);
        System.out.println(maps);
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值