JAVA中int类型数组怎么修改为泛型

发布时间:2021-11-24 14:56:18 作者:iii
来源:亿速云 阅读:162

这篇文章主要介绍“JAVA中int类型数组怎么修改为泛型”,在日常操作中,相信很多人在JAVA中int类型数组怎么修改为泛型问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JAVA中int类型数组怎么修改为泛型”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

int类型数组

先来一个简单的内容,这个是正常的,以为我在日常的开发中有的时候还是能遇见的,哈哈哈哈,正不正常就以我是不是用过作为标准

public class Main {

   public static void main(String[] args) {
       Array score=new Array(10);
       for(int i=0;i<8;i++){
           score.addLast(i);
       }

       score.add(1,100);
       score.addLast(99);
       System.out.println(score.toString());

       System.out.println(score.find(1));
       System.out.println(score.contains(1));
       System.out.println(score.remove(1));
       System.out.println(score.toString());
       System.out.println(score.removeElement(2));
       System.out.println(score.toString());
   }
}

修改为泛型

public class Array<T> {
   private T[] data;
   private int size;

   public Array() {
       this(10);
   }

   public Array(int capacity) {
       //java本身不支持直接new 一个泛型数组,所以用以下方法实现
       data = (T[])new Object[capacity];
       size = 0;
   }

   public int getSize() {
       return size;
   }

   public int getCapacity() {
       return data.length;
   }

   public boolean isEmpty() {
       return size == 0;
   }

   /**
    * 向数组末尾添加元素
    *
    * @param e
    */
   public void addLast(T e) {
       add(size, e);
   }

   /**
    * 向数组开头添加元素
    *
    * @param e
    */
   public void addFirst(T e) {
       add(0, e);
   }

   /**
    * 向任意合法位置添加元素
    *
    * @param index
    * @param e
    */
   public void add(int index, T e) {
       if (size == data.length) {
           throw new IllegalArgumentException("Add is fail.Array is full");
       }

       if (index < 0 || index > size) {
           throw new IllegalArgumentException("Add is fail.Require index >= 0 and index < size");
       }

       for (int i = size; i > index; i--) {
           data[i] = data[i - 1];
       }
       data[index] = e;
       size++;
   }

   /**
    * 获取索引位置的元素
    * 通过这种封装,用户无法查询未使用的空间,保证了数据的安全性。
    *
    * @param index
    * @return
    */
   public T get(int index) {
       if (index < 0 || index >= size) {
           throw new IllegalArgumentException("Get is failed.Index is illegal");
       }
       return data[index];
   }

   /**
    * 修改索引位置的元素
    *
    * @param index
    * @param e
    */
   public void set(int index, T e) {
       if (index < 0 || index >= size) {
           throw new IllegalArgumentException("Set is failed.Index is illegal");
       }
       data[index] = e;
   }

   /**
    * 数组中是否包含某个元素
    *
    * @param e
    * @return
    */
   public boolean contains(T e) {
       for (int i = 0; i < size; i++) {
           //注意值的比较应修改为equals方法
           if (data[i].equals(e)) {
               return true;
           }
       }
       return false;
   }

   /**
    * 查询数组中某个元素的索引
    *
    * @param e
    * @return 没有该元素则返回-1
    */
   public int find(T e) {
       for (int i = 0; i < size; i++) {
           if (data[i].equals(e)) {
               return i;
           }
       }
       return -1;
   }

   /**
    * 删除index位置的元素,并且返回该元素
    * 不用担心删除后原来size位置的元素,因为用无法访问到它。
    * 但是最好再写一句data[size]=null 具体原因需要了解java的垃圾回收机制
    *
    * @param index
    * @return
    */
   public T remove(int index) {
       if (index < 0 || index >= size) {
           throw new IllegalArgumentException("Remove failed.Require index >=0 and index < size");
       }

       T ret = data[index];
       for (int i = index; i < size - 1; i++) {
           data[i] = data[i + 1];
       }
       //注意维护size
       size--;
       data[size]=null;
       return ret;
   }

   /**
    * 不用担心数组为空的情况,因为数组如果为空,remove方法就会抛出异常
    * @return
    */
   public T removeFirst(){
       return remove(0);
   }

   public T removeLast(){
       return remove(size-1);
   }

   /**
    * 从数组中删除元素e
    * @param e
    */
   public boolean removeElement(T e){
       int index=find(e);
       if(index!=-1){
           remove(index);
           return true;
       }else{
           return false;
       }
   }

   /**
    * 重写toString()方法
    *
    * @return
    */
   @Override
   public String toString() {
       StringBuilder res = new StringBuilder();
       res.append(String.format("size= %d,capacity= %d\n", size, data.length));
       res.append("[");
       for (int i = 0; i < size; i++) {
           res.append(data[i]);
           if (i != size - 1) {
               res.append(",");
           }
       }
       res.append("]");
       return res.toString();
   }
}

增加数组大小

前面当我们向数组中添加元素时,如果index==size,表示数组已满。

if (size == data.length) {
   throw new IllegalArgumentException("Add is fail.Array is full");
}
123

现在可以考虑这样做,依然判断插入位置是否合法,但是当size等于数组长度时,自动为数组扩容——resize(2*data.length);
之所以是扩为原来的2倍,是因为这样扩容量的大小和原来容量大小有关,既不会过小也不会过大。

private void resize(int newCapacity){
   T[] newData=(T[])new Object[newCapacity];
   for(int i=0;i<size;i++){
       newData[i]=data[i];
   }
   data=newData;
}
1234567

减小数组大小

因为有了resize方法,实现起来就很简单了。在remove(int index)方法中,移除一个元素且维护size后,再加上对维护后的size的判断,如下。如果size已经变为capacity的一半,则将数组容量减半。

if(size==data.length/2){
   resize(data.length/2);
}
123

注意
resize()方法设为私有,是为了用户只需使用这个数组类,不必去顾虑数组的大小。

时间复杂度的分析

通过对addLast(T[] e)和removeLast(T[] e)时间复杂度的分析,我们发现都是O(n)级别的。但是,这样一般性地考虑最坏的情况在这种情景下是没有太大意义的。因为addLast(T[] e)和removeLast(T[] e)操作并不会经常触发resize(int newCapcity)操作。所以用均摊复杂度分析的话,你会发现这两个操作的均摊复杂度都是O(1)。因此resize(int newCapcity)这样一个比较耗时的操作,如果保证不会每次都会触发,就可以将它的操作耗时分摊到其他操作上。

现在再考虑另外一个场景,就是在addLast(T[] e)操作后,触发了resize(int newCapcity),然后再removeLast(T[] e),又触发了resize(int newCapcity);如此循环。像这样addLast(T[] e)和removeLast(T[] e)的时间复杂度都是O(n)级别的,这就是所谓的复杂度的震荡。以数组这个例子,之所以发生这种情况是因为我们在removeLast操作后,就接着进行了resize操作这样太着急了。那么该如何防止复杂度的震荡呢?
可以这样修改removeLast方法的代码。

if(size==data.length/4 && data.length/4!=0){
resize(data.length/2);
}

加上data.length/4!=0的判断是因为当data.length/4==0的时候,数组长度变为0,这是不合法的。

修改后的完整代码

public class Array<T> {
   private T[] data;
   private int size;

   public Array() {
       this(10);
   }

   public Array(int capacity) {
       //java本身不支持直接new 一个泛型数组,所以用以下方法实现
       data = (T[])new Object[capacity];
       size = 0;
   }

   public int getSize() {
       return size;
   }

   public int getCapacity() {
       return data.length;
   }

   public boolean isEmpty() {
       return size == 0;
   }

   /**
    * 向数组末尾添加元素
    *
    * @param e
    */
   public void addLast(T e) {
       add(size, e);
   }

   /**
    * 向数组开头添加元素
    *
    * @param e
    */
   public void addFirst(T e) {
       add(0, e);
   }

   /**
    * 向任意合法位置添加元素
    *
    * @param index
    * @param e
    */
   public void add(int index, T e) {
       /*if (size == data.length) {
           throw new IllegalArgumentException("Add is fail.Array is full");
       }*/

       if (index < 0 || index > size) {
           throw new IllegalArgumentException("Add is fail.Require index >= 0 and index < size");
       }

       if(size == data.length){
           resize(2*data.length);
       }

       for (int i = size; i > index; i--) {
           data[i] = data[i - 1];
       }
       data[index] = e;
       size++;
   }

   /**
    * 获取索引位置的元素
    * 通过这种封装,用户无法查询未使用的空间,保证了数据的安全性。
    *
    * @param index
    * @return
    */
   public T get(int index) {
       if (index < 0 || index >= size) {
           throw new IllegalArgumentException("Get is failed.Index is illegal");
       }
       return data[index];
   }

   /**
    * 修改索引位置的元素
    *
    * @param index
    * @param e
    */
   public void set(int index, T e) {
       if (index < 0 || index >= size) {
           throw new IllegalArgumentException("Set is failed.Index is illegal");
       }
       data[index] = e;
   }

   /**
    * 数组中是否包含某个元素
    *
    * @param e
    * @return
    */
   public boolean contains(T e) {
       for (int i = 0; i < size; i++) {
           //注意值的比较应修改为equals方法
           if (data[i].equals(e)) {
               return true;
           }
       }
       return false;
   }

   /**
    * 查询数组中某个元素的索引
    *
    * @param e
    * @return 没有该元素则返回-1
    */
   public int find(T e) {
       for (int i = 0; i < size; i++) {
           if (data[i].equals(e)) {
               return i;
           }
       }
       return -1;
   }

   /**
    * 删除index位置的元素,并且返回该元素
    * 不用担心删除后原来size位置的元素,因为用无法访问到它。
    * 但是最好再写一句data[size]=null 具体原因需要了解java的垃圾回收机制
    *
    * @param index
    * @return
    */
   public T remove(int index) {
       if (index < 0 || index >= size) {
           throw new IllegalArgumentException("Remove failed.Require index >=0 and index < size");
       }

       T ret = data[index];
       for (int i = index; i < size - 1; i++) {
           data[i] = data[i + 1];
       }
       //注意维护size
       size--;
       data[size]=null;

       if(size==data.length/4 && data.length/4!=0){
resize(data.length/2);
       }
       return ret;
   }

   /**
    * 不用担心数组为空的情况,因为数组如果为空,remove方法就会抛出异常
    * @return
    */
   public T removeFirst(){
       return remove(0);
   }

   public T removeLast(){
       return remove(size-1);
   }

   /**
    * 从数组中删除元素e
    * @param e
    */
   public boolean removeElement(T e){
       int index=find(e);
       if(index!=-1){
           remove(index);
           return true;
       }else{
           return false;
       }
   }

   /**
    * 重写toString()方法
    *
    * @return
    */
   @Override
   public String toString() {
       StringBuilder res = new StringBuilder();
       res.append(String.format("size= %d,capacity= %d\n", size, data.length));
       res.append("[");
       for (int i = 0; i < size; i++) {
           res.append(data[i]);
           if (i != size - 1) {
               res.append(",");
           }
       }
       res.append("]");
       return res.toString();
   }

   private void resize(int newCapacity){
       T[] newData=(T[])new Object[newCapacity];
       for(int i=0;i<size;i++){
           newData[i]=data[i];
       }
       data=newData;
   }
}

到此,关于“JAVA中int类型数组怎么修改为泛型”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

推荐阅读:
  1. java中如何判断是否为int类型
  2. java中的int数据类型

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

int java

上一篇:如何基于Ocelot的API网关Relay实现RPC

下一篇:MongoDB如何在线安装

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》