zoukankan      html  css  js  c++  java
  • Java 泛型的实际运用、使用数组实现栈

     

    1、泛型的实际应用——实现最小值函数

    自己设计一个泛型的获取数组最小值的函数,并且数组的元素类型要是Number的子类并且实现了Comparable接口。

    public <T extends Number & Comparable<? super T>> T min(T[] arr) {  //因为Number并没有implements Comparable,所以需要&一起检查类型
            if (arr == null || arr.length == 0)  //数组未初始化或是空数组
                return null;
            
            //如果数组有元素,就找到最小值        
            T min = arr[0];
            for (int i = 1; i < arr.length; i++) { //arr.length是数组的元素个数
                if (min.compareTo(arr[i]) > 0)  //>0说明min>arr[i]
                    min = arr[i];
            }
            return min;
            
    }

    min前面的T是返回值类型,传入T类型的数组,返回的最小值也是T类型。

    Comparable接口只有一个方法:compareTo(),比较2个的大小,返回一个int型的值,1表是前面的大,0表示2个相等,-1表示后面(括号里)的大。

    如果数组元素没有实现Comparable接口,直接大于、小于比较也行。

    测试:

        Integer minInteger = min(new Integer[]{1, 2, 3}); //int型数组
        Double minDouble = min(new Double[]{1.2, 2.2,4.5});//double型数组
        System.out.println(minInteger);
        System.out.println(minDouble);
        
        // String typeError = min(new String[]{"1","3"});//String类型的数组,报错,通不过编译,因为String不是extends Number

    为什么数值型数组使用的是Integer这些包装类型?因为基本类型没有实现Comparable接口,包装类型都实现了此接口。

    public final class Integer extends Number implements Comparable<Integer>
    
    public final class Character implements java.io.Serializable,Comparable<Character> 
    
    public final class String implements java.io.Serializable, Comparable<String>, CharSequence

    严格意义上来说,int、float、char等基本类型都不算是类,它们并没有继承Object,也就没有hashCode()、equals()之类的方法。基本类型算是和Object一个级别的。

    包装类型都是类,继承了Object。数值型的包装类型的直接父类都是Number类。

    2、使用数组实现栈

    自己实现一个栈,要求这个栈具有push()pop()(返回栈顶元素并出栈)、peek() (返回栈顶元素不出栈)、isEmpty()size()这些基本的方法。

    public class MyStack {
        private int[] arr; //存放栈中元素的数组。此处声明为int型数组,根据需要修改。也可以使用泛型
        private int capacity; //栈的容量
        private int count; //栈中元素数量
        private static final int GROW_FACTOR = 2; //成长因子。数组容量不够时,*2容量翻倍(要自己实现)
    
        //不带初始容量的构造方法。默认容量为10
        public MyStack() {
            this.capacity = 10;
            this.arr=new int[10];
            this.count = 0;
        }
    
        //带初始容量的构造方法
        public MyStack(int initialCapacity) {
            if (initialCapacity < 1)
                throw new IllegalArgumentException("Capacity is too small.");
            this.capacity = initialCapacity;
            this.arr = new int[initialCapacity];
            this.count = 0;
        }
    
        //数组扩容,内部调用,private
        private void addCapacity() {
            int newCapacity = capacity * GROW_FACTOR;
            arr = Arrays.copyOf(arr, newCapacity); //数组的容量确定后,后续不能修改,只能copy到新数组,arr指向新数组
            capacity = newCapacity;
        }
    
        //入栈
        public void push(int value) {
            if (count == capacity) { //先检查容量,满了就扩容
                addCapacity();
            }
            arr[count++] = value;
        }
    
        //返回栈顶元素并出栈。入栈暴露出来给外部调用,很多函数由栈自己调用(处理栈中元素),private。暴露出去给外部调用也行。
        private int pop() {
            if (count == 0)
                throw new IllegalArgumentException("Stack is empty.");
            count--; //数组中还是有这个元素,遍历栈(数组)要用count计数,不能直接遍历整个数组
            return arr[count];
        }
    
        //返回栈顶元素不出栈
        private int peek() {
            if (count == 0)
                throw new IllegalArgumentException("Stack is empty.");
            return arr[count-1];
        }
    
        //判断栈是否为空
        private boolean isEmpty() {
            return count == 0;
        }
    
        //返回栈中元素的个数
        private int size() {
            return count;
        }
        
    }

    使用:

    MyStack myStack = new MyStack(5);
    myStack.push(1);  //入栈
    myStack.push(2);

    上面红色标出的一句代码:

    arr = Arrays.copyOf(arr, newCapacity);

    Arrays.copyOf()有多个重载方法,对应不同类型数组的复制,看一下源码,以int[ ]为例:

    public static int[] copyOf(int[] original, int newLength) {
            int[] copy = new int[newLength];
            System.arraycopy(original, 0, copy, 0,
                             Math.min(original.length, newLength));
            return copy;
    }

    参数:源数组、新数组的长度。新建指定容量的数组,把源素组中的元素复制到新数组,返回新数组。

    如果newLength小于源数组的长度,则能复制多少就复制多少,直到把新数组装满;

    如果newLength大于源数组的长度,则把源数组的元素都复制过来,剩下的未填充的,全部填充元素类型的默认值。

  • 相关阅读:
    oracle 锁表查看与解锁
    oracle 监视索引是否使用
    oracle 查看数据库版本
    mybatis 中文做参数报错
    windows mysql绿色版配置
    maven使用本地jar包
    Java 使用Jedis连接Redis数据库(-)
    Linux 安装redis
    ELK之在CentOS7.5上使用rpm包安装配置ELK7版本
    Ubuntu-18.04更改安装源为国内源
  • 原文地址:https://www.cnblogs.com/chy18883701161/p/12492557.html
Copyright © 2011-2022 走看看