javase-day03

aClass_Person

package com.se.Genericity.aClass;

import java.util.Date;

/**
 *   泛型: 类型参数化。  定义期间,有些东西不确定是什么类型,在使用期间确定
 *        这样就可以使用泛型。给形参赋值具体类型名
 *   泛型类   泛型应用在类上。一般用在类名后,使用尖括号括起来。用大写字母作为泛型参数。
 *
 */

public class Person<T> {
    private T idCard;

    public Person(T idCard){
        this.idCard = idCard;
    }

    public static void main(String[] args) {
        //创建一个Person对象,需要给泛型参数赋值具体类型
        Person p1 = new Person<String>("123456");
        Person<String> p2 = new Person("123456");
        //泛型参数,只能赋值引用类型,不能赋值八大基本数据类型
        Person<Long> p3 = new Person<>(34567890L);
        Date date = new Date();
        //tips: 实例化过程中,可以只在一遍给泛型参数赋值,但是两边的尖括号都不可以省略
        Person<Date> p4 = new Person<>(date);
    }
}

/**
 *   当一个子类继承带有泛型的父类时,一般情况下要给泛型参数赋值具体类名
 */
class Student extends Person<Integer>{
    public Student(Integer idcard) {
        super(idcard);
    }
}

/**
 *   子类的泛型参数可以赋值给父类的泛型参数
 *   下面的例子就是 E赋值给了T
 */
class Teacher<E> extends Person<E>{
    public Teacher(E idcard) {
        super(idcard);
    }
}

/**
 * 如果 子类在定义期间,没有给泛型父类参数赋值,默认Object
 */
class President extends Person{
    public President(Object idcard) {
        super(idcard);
    }
}

bInterface_MyComparable

package com.se.Genericity.bInterface;

import java.util.Arrays;
import java.util.Comparator;

/**
 * 泛型接口: 泛型用在接口上
 */

public interface MyComparable<T, M> {
    //两种类型进行比较
    public int mycompare(T o1, M o2);

    public static void main(String[] args) {
        Employee[] employees = new Employee[3];
        employees[0] = new Employee("xin", 19);
        employees[1] = new Employee("zin", 18);
        employees[2] = new Employee("din", 17);

        //使用比较器接口,来重新定义比较规则
        // 从泛型的角度来说,在实例化接口时,要给泛型参数传具体类型
        Comparator c = new Comparator<Employee>() {
            //重写比较器里的compare方法
            public int compare(Employee o1, Employee o2) {
                //调用了自定义的员工类里的比较方法
                return o1.mycompare(o1, o2);
            }
        };
        Arrays.sort(employees, c);
        System.out.println(Arrays.toString(employees));
    }
}

//子类实现接口  通常子类要给泛型接口的泛型参数赋值具体类型名
//下面案例,就是给T和M都赋值了Employee这个类型
class Employee implements MyComparable<Employee, Employee> {
    String name;
    int age;

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

    public String toString() {
        return "[" + name + "," + age + "]";
    }

    public int mycompare(Employee o1, Employee o2) {
        return o2.age - o1.age;
    }
}

cMethod_MyUtil

package com.se.Genericity.cMethod;

import java.util.Objects;

/**
 * 泛型方法: 泛型应用在方法上位置位于返回值类型的前面
 * <p>
 * 案例演示: 定义一个工具类, 用于比较两个对象是否一样
 */

public class MyUtil {
    public static <T> boolean equals(T t1, T t2) {
        return t1.equals(t2);

    }

    public static void main(String[] args) {
        Cat c1 = new Cat("小花");
        Cat c2 = new Cat("小花");

        //泛型方法在调用期间,不需要指定具体类型,只需要传入具体类型,编译器会自动推断对象的类型
        //泛型方法调用期间,并没有给泛型参数赋值,下面的案例是c1给t1赋值,c2给t2赋值
        boolean result = MyUtil.equals(c1, c2);
        System.out.println(result);
    }
}

class Cat {
    String name;

    @Override
    public boolean equals(Object object) {
        if (this == object) return true;
        if (object == null || getClass() != object.getClass()) return false;
        Cat cat = (Cat) object;
        return Objects.equals(name, cat.name);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(name);
    }

    public Cat(String name) {
        this.name = name;
    }
}

dSymbol_MyUtil

package com.se.Genericity.dSymbol;

/**
 * 泛型通配符:?   用来表明不关心调用时的具体类型。
 */

import java.util.ArrayList;
import java.util.List;

public class MyUtil {
    /*
      将集合元素打印在控制台上
     */

    public static void print(List<?> list) {
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));

        }
    }

    /*
    上边界的定义: <? extends 具体类名>
          具体使用的时候,可以是上边界的任何子类型或者本类型
     */
    public static void print2(List<? extends Number> list) {
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }

    /*
    下边界的定义: <? super 具体类名>
          具体使用的时候,可以是下边界的任何父类型或者本类型
     */
    public static void print3(List<? super Integer> list) {
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }


    public static void main(String[] args) {
        List<Integer> nums = new ArrayList<Integer>();
        nums.add(1);
        nums.add(2);
        nums.add(3);
        MyUtil.print(nums);


        List<Long> ns = new ArrayList<Long>();
        ns.add(1L);
        ns.add(2L);
        ns.add(3L);
        MyUtil.print(ns);

        //上边界的测试
        print2(new ArrayList<Long>());
        print2(new ArrayList<Number>());
//        print2(new ArrayList<Object>());  最高到达的类型是Number,所以只能是Number或者Number的子类


        //下边界的测试
        print3(new ArrayList<Integer>());
        print3(new ArrayList<Number>());
        print3(new ArrayList<Object>());
//        print3(new ArrayList<Long>());  Long和Integer没有关系
    }
}

eDateStructrue_MyDoubleList

package com.se.Genericity.eDateStructrue;

import java.net.BindException;

/**
 * 自定义一个双链表的数据结构
 */
public class MyDoubleList<E> {
    // 新创建容器时,头部和尾部都没有节点,都是null;size是0。
    private Node headNode;  // 头部节点
    private Node tailNode;  // 尾部节点
    private int size;       // 元素个数

    /**
     * 添加元素到链表尾部
     *
     * @param e 要添加的元素
     */
    public void addLast(E e) {
        // 创建一个新节点,当前节点的element是e,preNode和nextNode都是null
        Node newNode = new Node(e);
        if (headNode == null) {
            // 如果链表为空,则头部节点和尾部节点都是当前节点
            headNode = newNode;
            tailNode = newNode;
        } else {
            // 将新节点添加到尾部
            newNode.preNode = tailNode;
            tailNode.nextNode = newNode;
            tailNode = newNode;
        }
        size++;  // 更新链表大小
    }

    /**
     * 将元素添加到链表头部
     *
     * @param e 要添加的元素
     */
    public void addFirst(E e) {
        Node newNode = new Node(e);
        if (headNode == null) {
            // 如果链表为空,则头部节点和尾部节点都是当前节点
            headNode = newNode;
            tailNode = newNode;
        } else {
            // 将新节点添加到头部
            newNode.nextNode = headNode;
            headNode.preNode = newNode;
            headNode = newNode;
        }
        size++;  // 更新链表大小
    }

    /**
     * 向指定索引位置添加元素
     *
     * @param index 要插入的位置索引
     * @param e     要插入的元素
     */
    public void addAt(int index, E e) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException("索引越界");
        }
        if (index == 0) {
            // 如果索引为0,则将元素添加到头部
            addFirst(e);
        } else if (index == size) {
            // 如果索引等于链表大小,则将元素添加到尾部
            addLast(e);
        } else {
            // 创建新节点
            Node newNode = new Node(e);
            // 找到索引位置的前一个节点
            Node current = headNode;
            for (int i = 0; i < index; i++) {
                current = current.nextNode;
            }
            // 插入新节点
            newNode.nextNode = current;
            newNode.preNode = current.preNode;
            current.preNode.nextNode = newNode;
            current.preNode = newNode;
            size++;  // 更新链表大小
        }
    }

    /**
     * 获取指定索引位置的元素
     *
     * @param index 要获取元素的索引
     * @return 指定索引位置的元素
     */
    public E get(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("索引越界");
        }
        //根据索引位置决定从头尾哪一侧开始遍历
        Node current = (index < size / 2) ? headNode : tailNode;
        for (int i = 0; i < index; i++) {
            current = current.nextNode;
        }
        // 返回当前节点的元素
        return current.element;
    }

    /**
     * 设置指定索引位置的元素
     *
     * @param index 要设置元素的索引
     * @param e     新的元素
     * @return 被替换的旧元素
     */
    public E set(int index, E e) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("索引越界");
        }
        //根据索引位置决定从头尾哪一侧开始遍历
        Node current = (index < size / 2) ? headNode : tailNode;
        for (int i = 0; i < index; i++) {
            current = current.nextNode;
        }
        // 保存旧元素
        E oldElement = current.element;
        // 设置新元素
        current.element = e;
        // 返回旧元素
        return oldElement;
    }

    /**
     * 移除指定索引位置的元素
     *
     * @param index 要移除元素的索引
     * @return 被移除的元素
     */
    public E remove(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("索引越界");
        }
        Node current = (index < size / 2) ? headNode : tailNode;
        for (int i = 0; i < index;i++ ){
            current = current.nextNode;
        }
        E oldElement = current.element;
        current.element=null;
        return oldElement;
    }

    /**
     * 返回链表的字符串表示形式
     *
     * @return 链表的字符串表示形式
     */
    public String toString() {
        StringBuilder sb = new StringBuilder();
        Node node = headNode;
        for (int i = 0; i < size; i++) {
            sb.append(node.element + ",");
            node = node.nextNode;
        }
        return sb.toString();
    }

    /**
     * 双链表的节点类
     */
    private class Node {
        E element;  // 当前节点的元素
        Node preNode;  // 前一个节点
        Node nextNode;  // 后一个节点

        /**
         * 一参构造器,给当前元素赋值
         *
         * @param element 节点的元素
         */
        public Node(E element) {
            this.element = element;
        }

        /**
         * 全参构造器
         *
         * @param element  节点的元素
         * @param preNode  前一个节点
         * @param nextNode 后一个节点
         */
        public Node(E element, Node preNode, Node nextNode) {
            this.element = element;
            this.preNode = preNode;
            this.nextNode = nextNode;
        }
    }

    /**
     * 主方法,用于测试双链表的功能
     *
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        MyDoubleList list = new MyDoubleList();
        list.addLast("a");
        list.addLast("b");
        list.addLast("c");
        System.out.println(list);  // 输出: a,b,c,
        list.addAt(0, "m");
        System.out.println(list);  // 输出: m,a,b,c,
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值