Java学习day18-集合框架2(泛型,工具类,TreeMap)

今日目标

  • 泛型
  • 集合工具类
  • 自带排序集合

一.泛型

​ Java泛型是jdk 1.5中引入的一个新特性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter)这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

  • 引入案例

    需求:输出集合中所有的字符串

ArrayList list = new ArrayList();
list.add("hello");
list.add("world");
list.add(666);
//需求:输出集合中所以的字符串
for (Object o:list){
    //会抛出类型转换异常
    System.out.println((String)o);
}
//异常分析:集合中数据类型不统一
  • 案例改进

    在源头上对数据进行约束,除了字符串,其它类型数据不能放入集合

//增加了泛型对类型进行约束
ArrayList <String>list = new ArrayList();
list.add("hello");
list.add("world");
list.add(666);//编译不通过
for (String s:list){//直接用String接收,无须强转
    //会抛出类型转换异常
    System.out.println(s);
}

1.泛型类

​ 类的后面定义一个或多个任意类型 ,可以在类的成员属性或方法中使用,例如:

public class Hello<T,A,B,C> {// <> 里表示声明
    private T t;
    private A a;
    private B b;
    private C c;
    //省略seter/getter和构造方法
    //应用于方法的形参
    public void fun1(A a){
        System.out.println(a);
    }
    public void fun2(B b){
        System.out.println(b);
    }
    public void fun3(C c){
        System.out.println(b);
    }
}
//测试类中,调用构造方法,传入不同的类型作为参数,创建对象。
  • 常见应用:List,Set,Map接口

案例:

  1. 定义一个Set集合,装入5本书(编号,书名,价格),且只能装入书籍。
  2. 定义一个Map集合,用来存入人物名称和对应的城池(刘备-荆州,张飞-徐州,关羽-樊城),使用泛型约束类型。
    在这里插入图片描述
public class City {
    private String city;
    @Override
    public String toString() {
        return "City{" +
                "city='" + city + '\'' +
                '}';
    }
    public City() {
    }
    public City(String city) {
        this.city = city;
    }
    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }
}
import javax.print.attribute.standard.Chromaticity;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Fx {
    public static void main(String[] args) {
        HashMap<String, City> map = new HashMap();
        map.put("关羽",new City("樊城"));
        map.put("张飞",new City("新野"));
        map.put("赵子龙",new City("徐州"));
        map.put("刘备",new City("荆州"));
        Set<String> keys = map.keySet();
        for (String s:keys){
            System.out.println(s+"---"+map.get(s));
        }
        Collection<City> values = map.values();

        for (City c:values){
            System.out.println(c);
        }
        Set<Map.Entry<String, City>> entries = map.entrySet();
        for (Map.Entry<String, City> entry:entries){
            System.out.println(entry.getKey()+"----"+entry.getValue());
        }
    }
}

在这里插入图片描述

  1. 定义一个人类People,声明3个泛型,尝试着从不同的方面去描述不同的人物,创建不同的对象。
 People<String , Double, Integer> people1 = new  People<>("曹操",999.99,26);
 People<String , Boolean, Character> people2 = new  People<>("刘备",false,'男');

在这里插入图片描述

public class People <A,B,C>{
    private A a;
    private B b;
    private C c;

    public People(A a, B b, C c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
}
public class TestPeople {
    public static void main(String[] args) {
        People p1 = new People<String, Double, Integer>("曹操", 999.99, 26);
        People p2 = new People<String, Boolean, Character>("刘备", false, '男');
        People <Boolean,Double,Character>p3 = new People("刘备", false, '男');
        //如果有类被指定,构造方法无需指定,若要指定要与类一致
        //People <Boolean,Double,Character>p3 = new People<String, Boolean, Character>("刘备", false, '男');
        People <String, Boolean, Character>p4 = new People<String, Boolean, Character>("刘备", false, '男');

    }
}

2.泛型接口

public interface Haha <T> {
    void ff(T t);
}
  • 编写实现类,重写ff方法

  • 常见应用:比较器Comparable

3.泛型方法

​ 在方法结构上声明一个或多个泛型,可用于方法的返回值或形参。

 public <T> void fun1(T t){
        System.out.println(t);
 }
 public <T> T fun1(T t){
        System.out.println(t);
     return t;
 }

4.泛型通配符

​ <? extends 类型> 表示某个类型或它的任意子类型

​ <? super 类型> 表示某个类型或它的任意父类型

案例

​ 动物类Animal有一个方法,返回动物的腿的个数。子类有狗狗和企鹅,分别重写该方法,返回各自腿的个数。

编写一个测试类,定义一个方法,该方法可以计算出一个动物集合List共有多少条腿,并输出。

再定义一个测试方法,分别计算一批动物(2只狗狗和3只企鹅)和一批狗狗(3只),一批企鹅(3只)的腿的数量。

public abstract class Animal {
    abstract int legs();
}
class Dog extends Animal{

    @Override
    int legs() {
        return 4;
    }
}
class Penguin extends Animal{

    @Override
    int legs() {
        return 2;
    }
}
class TestAni{
    static void calLegs(List<? extends Animal> animals){// List集合中可以是<? extends Animal> 这些类 也可用ArrayList<? extends Animal> animals
        int sum=0;
        for(Animal a:animals){
            sum+=a.legs();
        }
        System.out.println("这批动物的腿的个数:"+sum);
    }

    public static void main(String[] args) {
        //准备第一批:2只狗狗和3只企鹅
        ArrayList<Animal> animals = new ArrayList<>();
        animals.add(new Dog());
        animals.add(new Dog());
        animals.add(new Penguin());
        animals.add(new Penguin());
        animals.add(new Penguin());
        calLegs(animals);
        //准备第二批:3只狗狗
        ArrayList<Dog> animals2 = new ArrayList<>();
        animals2.add(new Dog());
        animals2.add(new Dog());
        animals2.add(new Dog());
        calLegs(animals2);
        //准备第三批:3只企鹅
        ArrayList<Penguin> animals3 = new ArrayList<>();
        animals3.add(new Penguin());
        animals3.add(new Penguin());
        animals3.add(new Penguin());
        calLegs(animals3);
    }
}

在这里插入图片描述

二.集合工具类

Collections工具类:是一个主要对List集合进行操作的工具类,里面包含静态方法。

  • 随机打乱shuffle
  • 排序sort
  • 交换swap
  • 查找binarySearch:前提是集合中的元素必须按某种规则升序排序
 public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        Collections.shuffle(list);
        System.out.println(list);
        Collections.sort(list);
        System.out.println(list);
        System.out.println(Collections.binarySearch(list,4));
        Collections.swap(list,1,2);
        System.out.println(list);
    }

在这里插入图片描述

public static void main(String[] args) {
        Integer [] arr={1,2,3};
        List<Integer> l = Arrays.asList(arr);
        //将数组转换为集合
        System.out.println(l);
        System.out.println(l.size());
        System.out.println("-------");
        int [] arr1={1,2,3};
        IntStream s = Arrays.stream(arr1);
        //遍历流
        s.forEach(System.out::println);
       /* Stream<Integer> ss = s.boxed();
        List<Integer> list = ss.collect(Collectors.toList());*/

        /*IntStream s = Arrays.stream(arr);
        s.forEach(System.out::println);
List<Integer> list = Arrays.stream(arr1).boxed().collect(Collectors.toList());

        System.out.println(list);
        System.out.println(list.size());*/
    }

在这里插入图片描述

案例:

1.现有5只猴子(姓名,年龄),将他们存入List集合中,先随机打乱,然后使用工具类,对这一群猴子按照年龄进行排序。

2.交换集合中的第一个和第三个猴子

3.查找名称叫 肉肉 的猴子

public class Monkey implements Comparable<Monkey>{
    @Override
    public int compareTo(Monkey o) {
        return this.age-o.age;
        //return this.name.compareTo(o.name);
    }
    private String name;
    private int age;
    @Override
    public String toString() {
        return "Monkey{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    public Monkey(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public Monkey() {
    }
    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;
    }
}
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class TestM {
    public static void main(String[] args) {
        Monkey[] monkeys={new Monkey("孙悟空",6),
                        new Monkey("菲菲",1),
                        new Monkey("肥肥",6),
                        new Monkey("狒狒",2),
                        new Monkey("肉肉",9)};
        List<Monkey> ms = Arrays.asList(monkeys);
        //随机打乱
        Collections.shuffle(ms);
        System.out.println(ms);
        //内部比较器,实体类实现Comparable接口
        Collections.sort(ms);
        System.out.println(ms);
        //再次随机打乱
       /* Collections.shuffle(ms);
        System.out.println(ms);*/
        //外部比较器 如下2种方式都行
        //Collections.sort(ms,new AgeCompare());
        /*Collections.sort(ms,( o1, o2)-> o1.getAge()-o2.getAge());
        System.out.println(ms);*/
        //查找 肉肉  查找什么属性,就要按照什么属性排序
            //内部比较器 查找
        int i = Collections.binarySearch(ms, new Monkey("肉肉", 2));
        System.out.println(i);
        //外部比较器查找
        //int i1 = Collections.binarySearch(ms, new Monkey("肉肉", 1), new NameCompare());
        /*int i2 = Collections.binarySearch(ms,new Monkey("肉肉", 1), (o1,o2)->o1.getName().compareTo(o2.getName()));
        System.out.println(i2);*/
    }
}
class NameCompare implements Comparator<Monkey> {
    @Override
    public int compare(Monkey o1, Monkey o2) {
        return o1.getName().compareTo(o2.getName());
    }
}
class AgeCompare implements Comparator<Monkey> {
    @Override
    public int compare(Monkey o1, Monkey o2) {
        return o1.getAge()-o2.getAge();
    }
}

三.TreeMap和TreeSet

  1. Set和Map的关系:

    set使用了map的key.

  2. 继承关系:

    Set接口有一个实现类是HashSet,还有一个子接口是SortedSet,该接口有一个实现类是TreeSet。
    在这里插入图片描述

TreeSet是一个有序集合,会根据自然排序排列或比较器进行排序,且没有重复元素,也没有下标。通过TreeMap实现。

TreeMap中的元素默认按照keys的自然排序排列或比较器进行排序。

  • 构造方法
//1.无参构造
new TreeSet<>();
new TreeMap<>();
//2.有参构造
new TreeSet<>(外部比较器Comparator);
new TreeMap<>(外部比较器Comparator);

案例:

1.将5个大象(姓名,年龄,体重)存入TreeSet中,并输出

public class Elephant implements Comparable<Elephant>{
    @Override
    public int compareTo(Elephant o) {
        return this.age-o.age;
    }
    private String name;
    private int age;
    private double weight;
    @Override
    public String toString() {
        return "Elephant{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", weight=" + weight +
                '}';
    }
    public Elephant() {
    }
    public Elephant(String name, int age, double weight) {
        this.name = name;
        this.age = age;
        this.weight = weight;
    }
    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;
    }
    public double getWeight() {
        return weight;
    }
    public void setWeight(double weight) {
        this.weight = weight;
    }
}
public class TestTreeSet {
    /*1.将5个大象(姓名,年龄,体重)存入TreeSet中,并输出
    * 2.给每一个大象安排一个主人,存入TreeMap中,并输出*/
    public static void main(String[] args) {
        fun1();
    }

    private static void fun2() {
        TreeMap<String,Elephant> es = new TreeMap<String,Elephant>();
        es.put("曹操",new Elephant("胖胖",2,3.6));
        es.put("曹植",new Elephant("肥肥",1,4.6));
        es.put("曹丕",new Elephant("菲菲",3,5.6));
        es.put("曹洪",new Elephant("毛毛",8,2.6));
        es.put("曹仁",new Elephant("壮壮",5,1.6));
        System.out.println(es);
    }

    private static void fun1() {
        //自然排序--基本数据类型
       /* TreeSet<Integer> es = new TreeSet();
        es.add(2);
        es.add(6);
        es.add(9);
        es.add(0);*/
       /* //内部比较器排序--对象
        TreeSet<Elephant> es = new TreeSet();
        es.add(new Elephant("胖胖",2,3.6));
        es.add(new Elephant("肥肥",1,4.6));
        es.add(new Elephant("菲菲",3,5.6));
        es.add(new Elephant("毛毛",8,2.6));
        es.add(new Elephant("壮壮",5,1.6));
        System.out.println(es);*/

        //外部比较器排序--对象
        TreeSet<Elephant> es = new TreeSet<Elephant>((o1, o2)-> Double.compare(o1.getWeight(),o2.getWeight()) );
        es.add(new Elephant("胖胖",2,3.6));
        es.add(new Elephant("肥肥",1,4.6));
        es.add(new Elephant("菲菲",3,5.6));
        es.add(new Elephant("毛毛",8,2.6));
        es.add(new Elephant("壮壮",5,1.6));
        System.out.println(es);
    }
}

2.给每一个大象安排一个主人,存入TreeMap中,并输出

public class Elephant {
    private String name;
    private int age;
    private double weight;

    @Override
    public String toString() {
        return "Elephant{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", weight=" + weight +
                '}'+"\n";
    }
    public Elephant() {
    }
    public Elephant(String name, int age, double weight) {
        this.name = name;
        this.age = age;
        this.weight = weight;
    }
    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;
    }
    public double getWeight() {
        return weight;
    }
    public void setWeight(double weight) {
        this.weight = weight;
    }
}
public static void main(String[] args) {
        TreeMap<String, Elephant> treeMap = new TreeMap<>();
        treeMap.put("曹操3",new Elephant("大1",2,3.6));
        treeMap.put("曹操2",new Elephant("大3",5,2.6));
        treeMap.put("曹操5",new Elephant("大5",1,4.6));
        treeMap.put("曹操6",new Elephant("大2",3,1.6));
        treeMap.put("曹操1",new Elephant("大6",4,6.6));
        System.out.println(treeMap);
    }

在这里插入图片描述

作业:

1.判断以下哪种书写时正确的?

在这里插入图片描述
1.4.5正确

2.将一系列字符串“hello”,“helloworld”,“how”,“do”,“you”,"what"存入TreeSet集合,要求按照字符串长度进行排序。
在这里插入图片描述

import java.util.Comparator;
import java.util.TreeSet;

public class Test {
    public static void main(String[] args) {
        TreeSet<String> set = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
if (o1.length()!=o2.length()){
    return o1.length()-o2.length();
}else {
    return 1;
}
            }
        });
        set.add("hello");
        set.add("helloworld");
        set.add("how");
        set.add("do");
        set.add("you");
        set.add("what");
        System.out.println(set);
    }
}

在这里插入图片描述

3.有一个记事本,可以记录做了哪些事情和每件事对应得次数。请输入10件事,可以重复,例如:

学java,

打球,

溜冰,

打球,

溜冰,

打球,

打球,

学java,

溜冰,

吃烧烤。

输入结束后,输出每件事和对应得次数,例如:

学java–2次

打球–4次

溜冰–3次

吃烧烤–1次

要求:所选的集合都要用泛型进行约束。

 HashMap<String, Integer> map = new HashMap<>();
        Scanner sc = new Scanner(System.in);
        for (int i = 1; i <=10 ; i++) {
            System.out.println("请输入第"+i+"件事");
            String s=sc.next();
            map.put(s,map.containsKey(s)?map.get(s)+1:1);
        }
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        for (Map.Entry<String, Integer> entry:entries){
            System.out.println(entry.getKey()+"的次数有"+entry.getValue());
        }

集合嵌套应用–选做:

4.有一个记事本,能记录周一到周天,每天做的所有事情和事情的次数,周而复始。小明在这个记事本上记录了3周,内容如下:

第1周

  • 周1:学java,逛街
  • 周2:打台球,旅游
  • 周3:溜冰,吃烧烤
  • 周4:打篮球,逛街,吃烧烤
  • 周5:学前端,溜冰
  • 周6:逛街,吃烧烤
  • 周7:旅游,打台球

第2周:

  • 周1:学java,学前端
  • 周2:打台球,溜冰,学java
  • 周3:旅游,吃烧烤
  • 周4:逛街,学java
  • 周5:学前端,旅游
  • 周6:逛街,打台球,吃烧烤
  • 周7:旅游,逛街,打台球,吃烧烤

第3周:

  • 周1:学java,学前端,学python
  • 周2:打台球,溜冰,学java,学C++
  • 周3:旅游,吃烧烤,吃冰淇淋
  • 周4:逛街,学java,吃烧烤
  • 周5:学前端,旅游,打高尔夫
  • 周6:逛街,打台球,吃烧烤,溜冰,蹦迪
  • 周7:旅游,逛街,打台球,吃烧烤,跑步

使用Scanner接收小明3周所做的所有事情,并存入相应的集合中。然后输出周一到周五(不区分第几周)小明所做的所有事情以及相应的次数。(要求:所选的集合都要用泛型进行约束。)

public static void main(String [] args){
        Scanner sc=new Scanner(System.in);
        //week 共有7个元素
        TreeMap<String, Map<String,Integer>> week = new TreeMap<String, Map<String,Integer>>();
        //数据录入
        for (int i = 1; i <= 2; i++) {
            System.out.println("第"+i+"周:");
            Map<String, Integer> map;
            for (int j = 1; j <=3 ; j++) {
                map= new HashMap<String, Integer>();//每天都会清空昨天的事情和次数
                System.out.println("周"+j+":");
                String things = sc.next();//旅游,逛街,旅游,打台球,吃烧烤,跑步
                String[] things_arr = things.split(",");
                for (String s : things_arr) {
                    //map存入的是:事情和次数
                    map.put(s,map.containsKey(s)?map.get(s)+1:1);
                }

                //第二周,第三周
                if(week.containsKey("周"+j)){
                    Map<String, Integer> map1 = week.get("周" + j);
                    mapAddMap(map1,map);
                   //week.put("周"+j,map);
                }else {//第一周
                    week.put("周"+j,map);
                }

            }
        }
        //数据输出 week
        Set<Map.Entry<String, Map<String, Integer>>> weeks = week.entrySet();
        for (Map.Entry<String, Map<String, Integer>> week1 : weeks) {
            System.out.println(week1.getKey()+":");
            Map<String, Integer> map = week1.getValue();
            Set<Map.Entry<String, Integer>> things = map.entrySet();
            for (Map.Entry<String, Integer> thing : things) {
                String key = thing.getKey();
                Integer count = thing.getValue();
                System.out.print(key+"--"+count+"次 \t");
            }
            System.out.println();//换行
        }
    }

    public static void mapAddMap(Map<String ,Integer> map1,Map<String ,Integer> map2){
        Set<String> map2key = map2.keySet();
        for (String m2key : map2key) {
            map1.put(m2key,map1.containsKey(m2key)?map1.get(m2key)+map2.get(m2key):map2.get(m2key));
        }
    }

Java学习顺序

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值