Day6 Java—集合

Day 6

集合

1. 集合结构

在这里插入图片描述

2. 概念

  • 简称集,用来存储多个元素的容器,每一种集合底层都封装了对应的数据结构

  • 数据结构:数组,链表,队列,哈希表,二叉树

  • 集合和数组区别

    • 元素类型
      • 集合:引用类型(存储基本类型时自动装箱)
      • 数组:基本类型,引用类型
    • 元素个数
      • 集合:不固定,可任意扩容
      • 数组:固定,不能改变容量
  • 不受容器大小限制,可以随时添加、删除元素

  • 提供了大量操作元素的方法(判断、获取等)

  • Java的集合体系

    • 单列集合(Collection)

      • List:ArrayList
      • Set: HashSet
    • 双列集合(Map)

      • Map:HashMap
public class Test6 {
    public static void main(String[] args) {

        Collection c=new ArrayList();

        //往集合中添加元素
        c.add(100);  //100原来是int类型,但是这里的参数对象是Object类,则进行了自动装箱,使int变为引用数据类型Integer
        c.add(3.14);
        c.add(100.5f);
        c.add(true);
        c.add(100l);
        c.add(new Object());

        //获取当前集合的长度
        int size = c.size();
        System.out.println("当前集合的长度为 "+size);

        //遍历集合中的元素
        Iterator iterator = c.iterator();//获取迭代器对象

        /*
            iterator.hasNext() 判断容器中是否存在下一个元素,如果存在返回true,同时对应的指针往下前进一步,不存在返回false
         */
        while (iterator.hasNext()){

            //获取元素中的数据
            Object object = iterator.next();
            System.out.println(object);
        }

        //清空集合中的元素
        c.clear();
        System.out.println("--------清空集合后--------");
        System.out.println("当前集合的长度为 "+c.size());
    }
}

/**
当前集合的长度为 6
100
3.14
100.5
true
100
java.lang.Object@4554617c
--------清空集合后--------
当前集合的长度为 0
*/

2.1 案例1

  • **需求:**创建一个集合对象
    —集合中存入猫、狗、兔子、鸟的实例,遍历集合
    —控制台打印
    —猫吃鱼
    —狗吃骨头
    —兔子吃胡萝卜
    —鸟吃虫子
/**
	Animal父类
	定义成员方法eat()
*/
public class Animal {

    public void eat(){};

}
/**
	Cat子类
	定义成员方法
	重写父类eat()
*/
public class Cat extends Animal{
    public void eat(){
        System.out.println("猫吃鱼");
    }
}
/**
	Test测试类
*/
public class Test {
    public static void main(String[] args) {
        
        Animal c=new Cat();               
        Animal d=new Dog();                
        Animal r=new Rabbit();
        Animal b=new Bird();

        Collection co=new ArrayList();    //创建集合实例对象
        co.add(c);
        co.add(d);
        co.add(r);
        co.add(b);

        Iterator it=co.iterator();    //创建迭代器,方便遍历
        while(it.hasNext()){
            Object o=it.next();    //元素是子类,要在下面进行转换成父类
            /*
            判断o是否是Animal类型
             */
            if(o instanceof Animal){
                Animal a=(Animal)o;     //将集合中的子类元素强转成父类
                a.eat();                //接着父类的引用指向子类对象(多态)
            }
        }
    }
}

/**
猫吃鱼
狗吃骨头
兔吃萝卜
鸟吃虫
*/

3. List集合

  • 特点:可重复,有序(存取数据顺序相同)
  • List l=new ArrayList();
    • 是线程不安全的
  • List l=new LinkedList()

3.1 案例

  • 分析

    • 向集合中添加元素的方法为: add()
    • 遍历集合的方式: for 循环
    • 获取集合中元素个数的方法: size()
  • 步骤

    • 创建集合对象
    • 分别创建三个Student对象
    • 使用 add() 方法将Student对象添加到集合中
    • 使用 for() 循环遍历集合并打印
public class Student {
    private String name;
    private int age;

    public Student(){};

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

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

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String toString(){
        return "Student{ name:"+name+", age:"+age+" }";
    }
}
public class Test {
    public static void main(String[] args) {
        List l1=new ArrayList();
        Student s1=new Student("张三",18);
        Student s2=new Student("李四",20);
        Student s3=new Student("王五",21);

        System.out.println("--------是否添加成功--------");
        boolean b1=l1.add(s1);
        System.out.println(b1);
        l1.add(s2);
        l1.add(s3);

        System.out.println("--------打印集合--------");
        System.out.println(l1);

        System.out.println("--------返回索引为1的元素--------");
        System.out.println(l1.get(1));
        System.out.println("--------返回集合长度--------");
        System.out.println(l1.size());

        System.out.println("--------遍历集合并输出--------");
        for(int i=0;i<l1.size();i++){
            System.out.println(l1.get(i));
        }

        System.out.println("--------增强for循环,简化遍历输出--------");
        for(Object o:l1){
            System.out.println(o);
        }
    }
}

/**
--------是否添加成功--------
true
--------打印集合--------
[Student{name='张三', age=18}, Student{name='李四', age=20}, Student{name='王五', age=21}]
--------返回索引为1的元素--------
Student{name='李四', age=20}
--------返回集合长度--------
3
--------遍历集合并输出--------
Student{name='张三', age=18}
Student{name='李四', age=20}
Student{name='王五', age=21}
--------增强for循环,简化遍历输出--------
Student{name='张三', age=18}
Student{name='李四', age=20}
Student{name='王五', age=21}

*/

4. 迭代器

  • 对过程的重复,称为迭代

  • ==迭代器是遍历Collection集合的通用方法。==可以在对集合遍历的同时进行添加,删除操作

  • 常用方法

    • next():返回迭代的下一个元素对象
    • hasNext():如果仍有元素可以迭代,则返回true
  • 列表迭代器是List体系独有的遍历方式,可以在对集合遍历的同时进行添加,删除等操作。

    • 但是必须通过调用列表迭代器来实现
public class Test1 {
    public static void main(String[] args) {
        List l1=new ArrayList();
        l1.add("a");
        l1.add("b");
        l1.add("c");

        Iterator it=l1.iterator();
        while(it.hasNext()){    //如果迭代器有元素,就一直迭代
            String s1=(String) it.next();
            System.out.println(s1);    //迭代遍历,并转换成字符串输出
        }

        /**
         * 需求:判断集合中如果有字符“b”,就在其后添加一个新字符:java
         */
        ListIterator lit=l1.listIterator();    //创建列表迭代器
        while(lit.hasNext()){     //是否存在下一个元素,存在返回true
            String s2=(String) lit.next();
            if("b".equals(s2)){
                lit.add("java");            //只有列表迭代器可以添加值
            }
            System.out.println(s2);         
        }
        System.out.println(l1);             //添加元素后输出列表
    }
}

/**
a
b
c
a
b
c
[a, b, java, c]
*/

5. 泛型

  • 即泛指任意类型,又叫参数化类型 (ParameterizedType),对具体类型的使用起到辅助作用,类似于方法的参数
  • 集合类泛型表示该集合中存放指定类型的元素
  • 格式: List<String> list2 = new ArrayList<>();
public class Test2 {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add(10);      //可编译,但会运行报错,类型转换异常 ClassCastException
        for (Object o : list) {
            String s = (String)o;
            System.out.println(s);
        }
        List<String> list2 = new ArrayList<>(); //使用泛型限制集合的元素类型为String,JDK7以后的版本,new的泛型可以写成<>
        list2.add("a");
        list2.add("b");
        list2.add("c");
        //list2.add(10);    //泛型后,list2只能添加String类型,此句会编译报错
    }
}

5.1 案例2

  • **需求:**创建一个arrayList集合(要使用泛型),里面存放10件商品实例

    ​ —过滤出价格大于100元的商品
    ​ —打印出所有的商品名称

/**
	定义Good类
	其中有名称,价格属性
	以及成员方法print(),用来打印所有商品名称
*/
public class Good {
    private String name;
    private double price;

    public Good(){};
    public Good(String name, double price) {
        this.name = name;
        this.price = price;
    }

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

    public void setPrice(double price) {
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    @Override
    public String toString() {
        return "Good{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }

    public void print(){
        System.out.println(this.name);
    }
}
/**
	测试类
*/
public class Test7 {
    public static void main(String[] args) {
        Good g1 = new Good("牛奶", 49.99);
        Good g2 = new Good("饼干", 26.00);
        Good g3 = new Good("奶粉", 108.88);
        Good g4 = new Good("婴儿车", 500.00);
        Good g5 = new Good("电视", 2000.00);
        Good g6 = new Good("电脑", 6000.00);
        Good g7 = new Good("鼠标", 30.8);
        Good g8 = new Good("风扇", 299.99);
        Good g9 = new Good("空调", 3500.00);
        Good g0 = new Good("键盘", 60.00);

        List<Good> l1 = new ArrayList<>();       //泛型,将list元素限制为Good类型
        l1.add(g0);
        l1.add(g1);
        l1.add(g2);
        l1.add(g3);
        l1.add(g4);
        l1.add(g5);
        l1.add(g6);
        l1.add(g7);
        l1.add(g8);
        l1.add(g9);

        System.out.println("--------商品列表--------");      //JDK8中新增的foreach遍历方法
        for (Object o : l1) {
            Good g = (Good) o;
            g.print();
        }
        System.out.println("--------超过100的商品--------");
        for (Object o : l1) {
            Good g = (Good) o;
            if (g.getPrice() > 100) {                  //过滤价值超过100的商品
                System.out.println(g.toString());
            }
        }
    }
}

/**
--------商品列表--------
键盘
牛奶
饼干
奶粉
婴儿车
电视
电脑
鼠标
风扇
空调
--------超过100的商品--------
Good{name='奶粉', price=108.88}
Good{name='婴儿车', price=500.0}
Good{name='电视', price=2000.0}
Good{name='电脑', price=6000.0}
Good{name='风扇', price=299.99}
Good{name='空调', price=3500.0}
*/

6. Collections工具类

  • 针对集合进行操作的工具类
  • 成员方法
    • sort(List) 根据元素的自然顺序,将指定列表按升序排序
    • max(Collection) 返回集合的最大元素
    • reverse(List) 反转List集合元素
    • shuffle(List) 使用默认的随机源随机置换指定的列表
public class Test3 {
    public static void main(String[] args) {
        List<Integer> l1=new ArrayList<>();
        l1.add(1);
        l1.add(7);
        l1.add(4);
        l1.add(6);
        l1.add(2);
        l1.add(4);
        l1.add(5);
        l1.add(9);
        l1.add(0);

        System.out.println(l1);
        System.out.println("集合中最大元素为:"+ Collections.max(l1));
        Collections.sort(l1);
        System.out.println("升序后的集合为:"+l1);
        Collections.reverse(l1);
        System.out.println("反转后的集合为:"+l1);
        Collections.shuffle((l1));
        System.out.println("打乱之后的集合为:"+l1);
    }
}

/**
[1, 7, 4, 6, 2, 4, 5, 9, 0]
集合中最大元素为:9
升序后的集合为:[0, 1, 2, 4, 4, 5, 6, 7, 9]
反转后的集合为:[9, 7, 6, 5, 4, 4, 2, 1, 0]
打乱之后的集合为:[1, 6, 4, 0, 5, 2, 4, 7, 9]
*/

7. Set集合

  • 不可重复,无序
public class Test4 {
    public static void main(String[] args) {
        Set<Student> set=new HashSet<>();
        Student s1=new Student("张三",18);
        Student s2=new Student("李四",19);
        Student s3=new Student("王五",20);
        Student s4=new Student("赵六",21);

        set.add(s1);
        set.add(s2);
        set.add(s3);
        set.add(s4);      //多次添加会自动依据equals()和hashCode()两种方法去重

        Iterator<Student> it=set.iterator();   //使用迭代器遍历并输出
        while(it.hasNext()){
            Student s=it.next();
            System.out.println(s);
        }

        System.out.println("--------打印集合--------");
        System.out.println(set);

        System.out.println("--------遍历集合并输出--------");
        for(Student student:set){
            System.out.println(student);      //打印顺序与添加顺序不同
        }
    }
}

/**
Student{name='李四', age=19}
Student{name='赵六', age=21}
Student{name='张三', age=18}
Student{name='王五', age=20}
--------打印集合--------
[Student{name='李四', age=19}, Student{name='赵六', age=21}, Student{name='张三', age=18}, Student{name='王五', age=20}]
--------遍历集合并输出--------
Student{name='李四', age=19}
Student{name='赵六', age=21}
Student{name='张三', age=18}
Student{name='王五', age=20}
*/

8. Map集合

  • 双列集合,元素由键值对(Entry)构成

  • key不可以重复,value可重复

  • 向map集合中添加㢝方法为:put()

  • 遍历集合的方式

    • 获取所有的key : keySet()
    • 遍历 keySet ,通过 key
    • 根据key获取 value : get()
  • 遍历keySet的方法:iterator()

  • map常用方法

    • 将一个集合所有元素复制过来:putAll()
    • 判断是否有此key:boolean b=map.containsKey();
    • 判断是否有此value:boolean b=map.containsValue();
    • 清空map:clear()
    • 根据key删除映射关系:remove(Object:Key);
  • 集合常识
    在这里插入图片描述

    • 集合的扩容机制
      • 当初始容量满了,就会触发扩容机制
    • 集合的初始容量
      • 每个集合初始容量不同,JDK版本不同,集合容量不同
    • 集合的加载因子
      • 触发扩容机制后,具体怎么扩容,例如:扩容为原来的1.5倍,则加载因子为1.
  • hashMap和hashTable的区别

    • 前者线程不安全,后者线程安全(线程同步)
    • 前者元素可为空,后者元素不允许为空(key和value都不能)
  • treeMap可根据key进行排序,因为底层封装的是二叉树

    • 注意:如果key元素类型为自定义类,则要在自定义类中实现比较接口Comparable,重写比较的方法
  • treeSet也可根据元素进行排序,但是如果泛型是自定义类,则也要重写比较方法

  • properties
    -在这里插入图片描述

public class Test5 {
    public static void main(String[] args) {
        Map<Integer,Student> map=new HashMap<>();    //创建一个map泛型——指定key为Integer类型,value为Student类型

        Student s1=new Student("张三",18);
        Student s2=new Student("李四",19);
        Student s3=new Student("王五",20);

        System.out.println(map.put(1,s2));   //利用键覆盖数值时会返回被覆盖的值
        System.out.println(map.put(1,s1));
        map.put(2,s1);
        map.put(3,s2);

        System.out.println("--------打印map集合--------");
        System.out.println(map);

        System.out.println("--------将map的key装成一个集合输出--------");
        Set<Integer> keys=map.keySet();      //获取map中的key,组成一个set集合
        System.out.println(keys);
        System.out.println("--------遍历key组成的迭代器并输出--------");
        Iterator<Integer> it=keys.iterator();   //将set集合变为一个迭代器
        while(it.hasNext()){          //遍历key组成的迭代器
            Integer key=it.next();
            System.out.println("key:"+key+"\tvalue:"+map.get(key));     //打印结果
        }

        System.out.println("--------遍历所有key并输出--------");   //key类型为Integer
        for(Integer integer:keys){    //使用for遍历所有key
            //System.out.println(map.get(integer));      //打印索引为keys的map元素
            System.out.println(integer);
        }

        System.out.println("--------遍历所有value并输出--------");    //value类型为Student
        for(Student value:map.values()){
            System.out.println(value);         //使用for遍历所有value
        }
    }
}


/**
null
Student{name='李四', age=19}
--------打印map集合--------
{1=Student{name='张三', age=18}, 2=Student{name='张三', age=18}, 3=Student{name='李四', age=19}}
--------将map的key装成一个集合输出--------
[1, 2, 3]
--------遍历key组成的迭代器并输出--------
key:1	value:Student{name='张三', age=18}
key:2	value:Student{name='张三', age=18}
key:3	value:Student{name='李四', age=19}
--------遍历所有key并输出--------
1
2
3
--------遍历所有value并输出--------
Student{name='张三', age=18}
Student{name='张三', age=18}
Student{name='李四', age=19}
*/

案例1:hashMap——统计字符出现次数

/*
法一
*/
public class HashChacter {
    public static void main(String[] args) {
        //键盘录入字符串
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String line = sc.next();

        //HashMap泛型,Key为Character(字符),value为Interger(次数)
        HashMap<Character, Integer> hashMap = new HashMap<>();

        for (int i = 0; i < line.length(); i++) {
            char key = line.charAt(i);   //返回指定位置的字符

            //此时hashmap为空
            //获取每一个字符在HashMap集合中对应的值,看其返回值
            Integer value = hashMap.get(key);
            //如果返回值为空,说明集合内没有该值,把该值存入进去,计次数为1
            if (value == null) {
                hashMap.put(key, 1);
            } else {
                //如果返回值不为空,说明字符已存在,计次数加1,并重新存入map
                value++;
                hashMap.put(key, value);
            }
        }

        //存放结果的字符序列
        StringBuilder result = new StringBuilder();

        Set<Character> ks = hashMap.keySet();
        for (Character key : ks) {
            Integer value = hashMap.get(key);
            result.append(key).append("(").append(value).append(") ");
        }
        System.out.println(result);
    }
}
/*
请输入一个字符串:
 abbcihcieiceicieciecietrbhtyjntymoj
a(1) b(3) c(6) e(5) h(2) i(7) j(2) m(1) n(1) o(1) r(1) t(3) y(2) 
*/
/*
法二
*/
public class HashCharacter {
    public static void main(String[] args) {
        String str="abbcihcieiceicieciecietrbhtyjntymoj";

        //将字符串转换成字符数组
        char[] c=str.toCharArray();

        //创建hashmap
        HashMap<Character,Integer> map=new HashMap<>();
        
        //遍历数组c,并装入map
        for(char ch:c){
            if(!map.containsKey(ch)){
                map.put(ch,1);
            }else{
                map.put(ch,map.get(ch)+1);
            }
        }
        System.out.println("=======统计次数======");

        Set<Map.Entry<Character,Integer>> result=map.entrySet();

        for (Map.Entry<Character,Integer> entry:result) {
            System.out.print(entry.getKey()+"("+entry.getValue()+") ");
        }
    }
}
/*
=======统计次数======
a(1) b(3) c(6) e(5) h(2) i(7) j(2) m(1) n(1) o(1) r(1) t(3) y(2) 
*/

案例2——统计字符、字母,单词个数(正则匹配)

  • 需求
    • 1、自定义一个结构,利用 hashMap 统计字符出现的次数。
    • 2、至少使用两种遍历方式打印每个字母出现的次数。
    • 3、统计每个单词出现的次数。并过滤超过3次的单词。
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Test1 {
        public static void main(String[] args) {
            //1、自定义一个结构,利用hashMap 统计字符出现的次数。
            getHashMapByStr();
            //2、至少使用两种遍历方式打印每个字母出现的次数。
            getForEach();
            //3、统计每个单词出现的次数。并过滤超过3次的单词。
            getWordNum();
        }

        /**
         * 3、统计每个单词出现的次数。并且过滤出现次数超过3次的单词
         */
        public static void getWordNum(){
            System.out.println("--------------------统计单词出现次数-----------------------");
            HashMap<String, Integer> map = new HashMap<>();
            String[] splits = getString().split("\\W+");

            for (String str:splits){
                //把所有大写字母转成小写字母
                String str2 = str.toLowerCase();
                if (map.containsKey(str2)){
                    map.put(str2,map.get(str2)+1);
                }else {
                    map.put(str2,1);
                }
            }
            System.out.println(map);

            //遍历map集合
//            Set<Map.Entry<String, Integer>> entries = map.entrySet();
//
//            for (Map.Entry<String, Integer> entry:entries){
//
//                System.out.println(entry.getKey()+" 出现次数:"+entry.getValue());
//            }

            System.out.println("-------------打印出现次数超过3次的单词(大小写不敏感)-------------------------");
            Set<Map.Entry<String, Integer>> entries = map.entrySet();
            for (Map.Entry<String, Integer> entry:entries){
                if (entry.getValue()>3){
                    System.out.println(entry.getKey()+" 出现次数:"+entry.getValue());
                }
            }
        }

        /**
        * 2、至少使用两种遍历方式打印每个字母出现的次数。
        */
        public static void getForEach(){
            HashMap<String, Integer> map = new HashMap<>();
            String[] splits = getString().split("");
            for (String str: splits){
                if (map.containsKey(str) && str.matches("\\w")){
                    map.put(str,map.get(str)+1);
                }else if (str.matches("\\w")){
                    map.put(str,1);
                }
            }

            System.out.println("------------------至少使用两种遍历方式打印字母出现次数---------------------");

            Set<String> strings = map.keySet();
            Iterator<String> iterator = strings.iterator();
            while (iterator.hasNext()){
                String next = iterator.next();
                Integer integer = map.get(next);
                System.out.println("字母 "+next+" 出现次数:"+integer);
            }
        }

        /**
        * 1、自定义一个结构,利用hashMap 统计字符出现的次数。
        */
        public static void getHashMapByStr(){

            System.out.println("-------------------------统计字符出现次数-----------------------------");
            HashMap<String, Integer> map = new HashMap<>();
            String[] splits = getString().split("");
            for (String s:splits){
                //把空格或者换行符筛选出去 !s.matches(" +|\n")
                if (map.containsKey(s) && !s.matches(" +|\n")){
                    map.put(s,map.get(s)+1);//如果有这个字符的存在 在当前基础上加一
                }else if (!s.matches(" +|\n")){
                    map.put(s,1);
                }
            }
            System.out.println(map);

//            //将map集合转成set集合
//            Set<Map.Entry<String, Integer>> entries = map.entrySet();
//            //遍历set集合
//            Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
//            while (iterator.hasNext()){
//                Map.Entry<String, Integer> next = iterator.next();
//                System.out.println(next.getKey() + "的个数是" +next.getValue());
//            }
        }

        public static String getString(){
            String getSring = "Tree bins (i.e., bins whose elements are all TreeNodes) are\n" +
                    "     * ordered primarily by hashCode, but in the case of ties, if two\n" +
                    "     * elements are of the same \"class C implements Comparable<C>\",\n" +
                    "     * type then their compareTo method is used for ordering. (We\n" +
                    "     * conservatively check generic types via reflection to validate\n" +
                    "     * this -- see method comparableClassFor).  The added complexity\n" +
                    "     * of tree bins is worthwhile in providing worst-case O(log n)\n" +
                    "     * operations when keys either have distinct hashes or are\n" +
                    "     * orderable, Thus, performance degrades gracefully under\n" +
                    "     * accidental or malicious usages in which hashCode() methods\n" +
                    "     * return values that are poorly distributed, as well as those in\n" +
                    "     * which many keys share a hashCode, so long as they are also\n" +
                    "     * Comparable. (If neither of these apply, we may waste about a\n" +
                    "     * factor of two in time and space compared to taking no\n" +
                    "     * precautions. But the only known cases stem from poor user\n" +
                    "     * programming practices that are already so slow that this makes\n" +
                    "     * little difference.)";
            return getSring;
        }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值