day18 Java 泛型 静态导入 可变参数 set


I know, i know
地球另一端有你陪我




一、 泛型

泛型,即“参数化类型”。经数据的类型转为参数,转变为类似变量的存在
然后在调用时传入具体的类型(类型实参)
能够避免在在使用数据类型时犯错

1、 泛型类

在类中,使用泛型

class Pokemon <E,T> {
    
    
    private E name;
    private T level;
    ...
}

	Pokemon <String,Integer> pokemon = new Pokemon <String,Integer> ();
    pokemon.setName("piplup");
    pokemon.setLevel(5);

2、 泛型方法

在方法中,使用泛型

	public <E> void show(E a){
    
    
		System.out.println(a);
	}
	show("fgh");

3、 泛型接口

接口中使用泛型

public interface Pokemon1 <E> {
    
    
    public abstract void show(E e);
}
public class Generic3 <E> implements Pokemon1 <E> {
    
    
    @Override
    public void show(E e) {
    
    
        System.out.println(e);
    }
}

4、 通配符

任意类型 <?>
如果没有明确,可以传入Object以及任意的Java类了

向下限定 <? extends E>
只允许传入E及其子类

向上限定 <? super E>
只允许传入E及其父类


二、 静态导入

格式:import static 包名….类名.方法名;
可以直接导入到方法的级别

注意事项:
1、方法必须是静态
2、若本类有其他的方法同静态导入的方法重名,优先使用本类中的方法
3、针对2,可以通过调用方法时增加前缀强制调用其他类中的同名静态方法
3、若静态导入两个重名的方法,系统将会报错


三、 可变参数

1、格式
修饰符 返回值类型 方法名(数据类型… 变量名){}

2、目的
解决需要处理不同参数数量时,需要重新重载方法

3、注意
此处的 ”数据类型…“ 相当于一个数组
如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个

    private static int sum(int... ints){
    
    
        int count = 0;
        for (int i : ints) {
    
    
            count += i;
        }
        return count;
    }

	int i = sum(1,2,3,4);
    System.out.println(i);

四、 set 集

元素唯一,且元素通常无序(存储顺序和取出顺序不一致)

有时候,顺序可能是正好与取出遍历顺序一致,或者运行多次都一样
但是这并不代表有序,可能是当前存放的元素较少

1、 HashSet

此类实现Set接口,由哈希表(实际为HashMap实例)支持。线程不安全,效率高
元素唯一,元素无序

该类的 add() 方法中,底层调用的是HashMap中的put()方法
最终调用的是HashMap中的putVal()方法
对于新加入的元素

会先判断 HashSet 底层的 HashMap 是否初始化,若无就先初始化
接着根据新元素的哈希值,查找该树中存储同样哈希值的位置
若位置为 null ,说明之前无该元素,直接插入
若找到位置,说明之前有同样哈希值的元素,继续调用 equals() 方法比较内容
┕  若返回 true,说明有重复元素了,此时会做一次覆盖,等同未添加
┕  若返回 false,说明无重复元素,直接插入

2、 LinkedHashSet

底层是哈希表和链表组成
哈希表保证元素的唯一性
链表保证的元素的顺序、有序(存储和取出的顺序一致)

3、 关于 set 中的去重

通常会使用 idea 默认提供的重写方法
请添加图片描述
此处的第一个勾,会影响是否判断继承关系

	//	未勾选选项,set不去重,equals返回false
    @Override
    public boolean equals(Object o) {
    
    
        if (this == o) return true;

        //	如果 o 为空,或二者所属类不同
        //	只要不从属一个类,返回 false
        * if (o == null || getClass() != o.getClass())
        * return false;

        Pokemon pokemon = (Pokemon) o;
        return level == pokemon.level &&
                dVS == pokemon.dVS &&
                Objects.equals(name, pokemon.name);
    }

    //	勾选选项,set去重,equals返回true 
    @Override
    public boolean equals(Object o) {
    
    
        if (this == o) return true;

        //	若是 Pokemon 的实例,继续向下比较内容
        //	若不是 Pokemon 的实例,返回 false
        * if (!(o instanceof Pokemon))
        * return false;

        Pokemon pokemon = (Pokemon) o;
        return level == pokemon.level &&
                dVS == pokemon.dVS &&
                Objects.equals(name, pokemon.name);
    }

4、 TreeSet

元素唯一,且元素的顺序可以按照某种规则进行排序

排序的方式有两种:
1、自然排序
2、比较器排序

4.1 自然排序

无参构造内部元素默认是自然排序,可以对基本数据类型等简单类型排序

	TreeSet<Integer> ts1 = new TreeSet<Integer>();
	ts1.add(6);
    ts1.add(5);
    ts1.add(4);
    ts1.add(3);
    ts1.add(3);
    for (Integer i : ts1) {
    
    
        System.out.print(i + " ");
    }
    //	3 4 5 6 

复杂引用类型,如自定义对象,需要实现接口 Comparable<> ,重写自然排序方法
根据 level 排序

class Pokemon1 implements Comparable<Pokemon1>{
    
    
	...
    @Override
    public int compareTo(Pokemon1 o) {
    
    
        //	插入的是调用方法者,即 this
        int i1 = this.getLevel() - o.getLevel();
        //  若 level 相等,继续比较二者 name
        int i2 = (i1 == 0 ? this.name.compareTo(o.name) : i1);
        return i2;
    }
}
	TreeSet<Pokemon1> ts = new TreeSet<Pokemon1>();
	Pokemon1 p1 = new Pokemon1("ralts", 5);
    Pokemon1 p2 = new Pokemon1("piplup", 5);
    Pokemon1 p3 = new Pokemon1("piplup", 5);
    Pokemon1 p4 = new Pokemon1("lapras", 30);

    ts.add(p1);
    ts.add(p2);
    ts.add(p3);
    ts.add(p4);
    
    System.out.println(ts);
	//	[{name='piplup', level=5}, {name='ralts', level=5},
	//   {name='lapras', level=30}]

4.2 比较器排序

在创建集合的时候,调用带参数的构造方法,这个参数是实现了Comparator接口的子类对象

	// 采用匿名内部类
    TreeSet<Pokemon2> ts = new TreeSet<Pokemon2>(new Comparator<Pokemon2>() {
    
    
        @Override
        public int compare(Pokemon2 o1, Pokemon2 o2) {
    
    
            //插入的是 o1,o2 相当于该红黑树
            int i1 = o1.getLevel() - o2.getLevel();
            int i2 = (i1 == 0 ? o1.getName().compareTo(o2.getName()) : i1);
            return i2;
        }
    });

    Pokemon2 p1 = new Pokemon2("piplup",5);
    Pokemon2 p2 = new Pokemon2("piplup",5);
    Pokemon2 p3 = new Pokemon2("ralts",10);
    Pokemon2 p4 = new Pokemon2("lapras",30);
    Pokemon2 p5 = new Pokemon2("gardevoir",50);
    Pokemon2 p6 = new Pokemon2("piplup",10);

    ts.add(p1);
    ts.add(p2);
    ts.add(p3);
    ts.add(p4);
    ts.add(p5);
    ts.add(p6);

    System.out.println(ts);
    //	[{piplup,5}, {piplup,10}, {ralts,10}, {lapras,30}, {gardevoir,50}]








总结

泛型类

class Pokemon <E,T> {
    
    }

泛型方法

public <E> void show(E a){
    
    }

泛型接口

public interface Pokemon1 <E> {
    
    
    public abstract void show(E e);
}
public class Generic3 <E> implements Pokemon1 <E> {
    
    }

静态导入概述
格式:import static 包名….类名.方法名;

HashSet
此类实现Set接口,由哈希表(实际为HashMap实例)支持。线程不安全,效率高
元素唯一,元素无序

HashSet
此类实现Set接口,由哈希表(实际为HashMap实例)支持。线程不安全,效率高
元素唯一,元素无序

TreeSet
元素唯一,且元素的顺序可以按照某种规则进行排序
排序的方式有两种:
1、自然排序
2、比较器排序

猜你喜欢

转载自blog.csdn.net/qq_41464008/article/details/120770424