前言:自制简陋动态数组,加深对原理的理解
(用stream去重非常非常好!!!)
1.add方法与toString方法
1 2 3 4
| @Override public String toString() { return Arrays.toString(array); }
|
ArrayList 类和简单数组都有其对应的 toString 实现,它们可以直接与 Arrays.toString() 配合使用。对于简单数组,Arrays.toString() 能够直接处理因为它被重载了多次以处理不同基本类型的数组(比如 int[], char[], double[] 等)以及对象数组(比如 String[], Integer[], Object[] 等)。
当你创建自己的动态数组类时,这个类是一个自定义的对象,不是数组类型。Arrays.toString() 方法不知道如何处理这个类的实例,因为它不是一个数组。它只能接受一个真正的数组作为参数。
如果你的动态数组类内部使用了一个原生数组来存储元素,你需要在类的 toString() 方法中调用 Arrays.toString() 并传入那个内部数组。
当你调用 System.out.println(instance);,Java 会自动调用你为你的动态数组类提供的 toString() 方法,而该方法会返回 Arrays.toString(array) 的结果,其中 array 是你的内部存储结构。这样就可以打印出动态数组的内容了
2.size为0时第一次添加index为0怎么办?怎么处理这个逻辑?看看源码别人是怎么写的。
1 2 3 4 5 6 7 8 9 10
| public void add(int index, int element) { if (index >= 0 && index < size) { System.arraycopy(array, index, array, index + 1, size - index); array[index] = element; size++; } else if (index==size) { } else System.out.println("ArrayIndexOutOfBoundsException!");
|
ArrayList:利用空参创建集合,在底层创建一个默认长度为0的数组,添加第一个元素时,底层会创建一个长度为10的数组。这就很好的解决了问题!
size的两个含义:元素个数和下次应存的位置。
3.很好的遍历方式forEach
1 2 3 4 5 6
| public void forEach(Consumer<Integer> consumer){ for (int i = 0; i < size; i++) { consumer.accept(array[i]); } }
|
它使用了 Java 的函数式编程特性。方法 forEach 接受一个 Consumer<Integer> 类型的参数,这个参数是一个函数式接口,代表了接受单个输入参数并且不返回结果的操作。在这个方法中,Consumer<Integer> 接口用来对整数进行操作。外部则可以使用lambda表达式进行想要的操作。
函数式编程的第一个特点就是可以把函数作为参数传递给另一个函数,也就是所谓的高阶函数。例如,对数组进行排序,可以传入一个排序函数作为参数:
1 2
| String[] array = { "orange", "Pear", "Apple" }; Arrays.sort(array, String::compareToIgnoreCase);
|
函数式编程的第二个特点就是可以返回一个函数,这样就可以实现闭包或者惰性计算:
以上两个特点还仅仅是简化了代码。从代码的可维护性上讲,函数式编程最大的好处是引用透明,即函数运行的结果只依赖于输入的参数,而不依赖于外部状态,因此,我们常常说函数式编程没有副作用。
没有副作用有个巨大的好处,就是函数内部无状态,即输入确定,输出就是确定的,容易测试和维护。
4.迭代器遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Override public Iterator<Integer> iterator() { return new Iterator<Integer>() { int i=0; @Override public boolean hasNext() { return i<size; } @Override public Integer next() { return array[i++]; } }; }
|
5.流(超棒的)
1 2 3 4 5
| public IntStream stream(){ return IntStream.of(Arrays.copyOfRange(array,0,size)); }
|
6.完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
| package Demo5;
import java.util.Arrays; import java.util.Iterator; import java.util.function.Consumer; import java.util.stream.IntStream;
public class DynamicArray implements Iterable<Integer> { private int size; private int capacity; private int[] array;
public DynamicArray() { array = null; size = 0; } public void rangeCheck(int index){ if (index < 0 || index >= size) throw new IndexOutOfBoundsException("ArrayIndexOutOfBoundsException"); }
public void ensureCapacity(int minCapacity) { if (array == null) array = new int[Math.max(minCapacity, 10)]; else if (array.length < minCapacity) { int newCapacity = array.length * 2; if (newCapacity < minCapacity) newCapacity = minCapacity; array = Arrays.copyOf(array, newCapacity); } }
public void add(int index, int element) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("ArrayIndexOutOfBoundsException"); ensureCapacity(size + 1); if (index < size) System.arraycopy(array, index, array, index + 1, size - index); array[index] = element; size++; } public int remove(int index){ rangeCheck(index); int removed=array[index]; if(index<size-1) System.arraycopy(array,index+1,array,index,size-index-1); size--; return removed; } public void foreach(Consumer<Integer> consumer){ for (int i = 0; i < size; i++) { consumer.accept(array[i]); } } @Override public Iterator<Integer> iterator() { return new Iterator<Integer>() { int i=0; @Override public boolean hasNext() { return i<size; } @Override public Integer next() { return array[i++]; } }; } public IntStream stream(){ return IntStream.of(Arrays.copyOfRange(array,0,size)); } public int get(int index) { rangeCheck(index); return array[index]; }
public int size() { return size; }
public boolean isEmpty() { return size == 0; } @Override public String toString() { return Arrays.toString(Arrays.copyOf(array,size)); } }
|