Maison  >  Article  >  Java  >  Chapitre d'amélioration de Java (19) -----Matrice 2

Chapitre d'amélioration de Java (19) -----Matrice 2

黄舟
黄舟original
2017-02-10 11:51:331038parcourir

La section précédente a principalement présenté les concepts de base des tableaux et est allée un peu plus loin dans ce qu'est un tableau. Dans cet article de blog, nous introduisons principalement d'autres aspects des tableaux.

3. Performances ? Veuillez donner la priorité aux tableaux

Il existe de nombreuses façons de stocker une série de données en Java, et sont-elles beaucoup plus pratiques à utiliser que les tableaux ? Mais pourquoi devons-nous encore utiliser des tableaux au lieu de les remplacer ? Les tableaux diffèrent des autres types de conteneurs dans trois domaines : l'efficacité, le type et la capacité à contenir des types primitifs. En Java, un tableau est le moyen le plus efficace de stocker et d'accéder de manière aléatoire à une séquence de références d'objets.

Les tableaux sont de moins en moins utilisés dans la conception de projets, et ils ne sont en effet pas aussi pratiques à utiliser que List et Set. Cependant, Les tableaux présentent encore certains avantages sur certains aspects, tels que la vitesse, et la couche inférieure des classes de collection est également implémentée via des tableaux.

--------这是ArrayList的add()------
    public boolean add(E e) {
    ensureCapacity(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
    }

 Ce qui suit utilise des tableaux et des listes pour effectuer certaines opérations de comparaison.

1.Résumé


Long time1 = System.currentTimeMillis();
        for(int i = 0 ; i < 100000000 ;i++){
            sum += arrays[i%10];
        }
        Long time2 = System.currentTimeMillis();
        System.out.println("数组求和所花费时间:" + (time2 - time1) + "毫秒");
        Long time3 = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            sum  += list.get(i%10);
        }
        Long time4 = System.currentTimeMillis();
        System.out.println("List求和所花费时间:" + (time4 - time3) + "毫秒");
--------------Output:
数组求和所花费时间:696毫秒
List求和所花费时间:3498毫秒


D'après la consommation de temps ci-dessus, la vitesse de la gamme de types de base de types de base est environ 5 fois supérieure à la collecte. En fait, dans la collection list, il y a une action fatale dans la sommation : list.get(i). Cette action est une action de déballage. L'objet Integer est automatiquement converti en un type de base int via la méthode intValue, ce qui entraîne une consommation inutile de performances.

Veuillez donc donner la priorité au tableau de la scène avec des exigences de performances élevées.

 

4. Tableau de longueur variable ?

 Les tableaux sont de longueur fixe et la longueur ne peut pas être modifiée une fois initialisée et déclarée. C'est très gênant pour nous dans le développement réel. Si nous sommes intelligents, nous pouvons certainement trouver un moyen d'y parvenir. Tout comme Java ne peut pas implémenter l'héritage multiple, nous pouvons également utiliser des classes et des interfaces internes pour y parvenir (veuillez vous référer au chapitre sur l'amélioration de Java (9) ----- Implémentation de l'héritage multiple).

 Alors, comment implémenter un tableau de longueur variable ? Nous pouvons utiliser l’idée d’expansion dans la méthode add de la collection List pour simuler l’implémentation. Voici la méthode d'expansion pour ArrayList :

public void ensureCapacity(int minCapacity) {
        modCount++;  
        int oldCapacity = elementData.length;
        /**
         * 若当前需要的长度超过数组长度时进行扩容处理
         */
        if (minCapacity > oldCapacity) {
            Object oldData[] = elementData;    
            int newCapacity = (oldCapacity * 3) / 2 + 1;    //扩容
            if (newCapacity < minCapacity)
                newCapacity = minCapacity;
            //拷贝数组,生成新的数组
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
    }

après l'instruction if. L'idée est de copier le tableau d'origine dans un nouveau tableau, et le nouveau tableau mesure 1,5 fois la longueur du tableau d'origine. Le code d'expansion du tableau simulé est donc le suivant :

public class ArrayUtils {
    /**
     * @desc 对数组进行扩容
     * @author chenssy
     * @data 2013-12-8
     * @param <T>
     * @param datas 原始数组
     * @param newLen 扩容大小
     * @return T[]
     */
    public static <T> T[] expandCapacity(T[] datas,int newLen){
        newLen = newLen < 0 ? datas.length :datas.length + newLen;   
        //生成一个新的数组
        return Arrays.copyOf(datas, newLen);
    }
    
    /**
     * @desc 对数组进行扩容处理,1.5倍
     * @author chenssy
     * @data 2013-12-8
     * @param <T>
     * @param datas  原始数组
     * @return T[]
     */
    public static <T> T[] expandCapacity(T[] datas){
        int newLen = (datas.length * 3) / 2;      //扩容原始数组的1.5倍
        //生成一个新的数组
        return Arrays.copyOf(datas, newLen);
    }
    
    /**
     * @desc 对数组进行扩容处理,
     * @author chenssy
     * @data 2013-12-8
     * @param <T>
     * @param datas 原始数组
     * @param mulitiple 扩容的倍数
     * @return T[]
     */
    public static <T> T[] expandCapacityMul(T[] datas,int mulitiple){
        mulitiple = mulitiple < 0 ? 1 : mulitiple;
        int newLen = datas.length * mulitiple;
        return Arrays.copyOf(datas,newLen );
    }
}

Grâce à ce détour, nous pouvons réaliser Extension du tableau. Par conséquent, si vous avez vraiment besoin d'un ensemble de données de longueur variable dans votre projet, les tableaux sont également à prendre en considération. Nous ne pouvons pas les exclure car ils sont de longueur fixe !

5. Problème de copie de tableau

Copier un par un est très gênant, j'utilise donc simplement List.toArray() méthode pour le convertir en tableau puis le copier via Arrays.copyOf Après l'avoir converti en collection, je trouve personnellement cela très pratique, mais je ne sais pas si je suis tombé dans le piège ! Nous savons que si l'élément du tableau est un objet, les données du tableau sont une référence d'objet

public class Test {
    public static void main(String[] args) {
        Person person_01 = new Person("chenssy_01");
        
        Person[] persons1 = new Person[]{person_01};
        Person[] persons2 = Arrays.copyOf(persons1,persons1.length);
        
        System.out.println("数组persons1:");
        display(persons1);
        System.out.println("---------------------");
        System.out.println("数组persons2:");
        display(persons2);
        //改变其值
        persons2[0].setName("chessy_02");
        System.out.println("------------改变其值后------------");
        System.out.println("数组persons1:");
        display(persons1);
        System.out.println("---------------------");
        System.out.println("数组persons2:");
        display(persons2);
    }
    public static void display(Person[] persons){
        for(Person person : persons){
            System.out.println(person.toString());
        }
    }
}
-------------Output:
数组persons1:
姓名是:chenssy_01
---------------------
数组persons2:
姓名是:chenssy_01
------------改变其值后------------
数组persons1:
姓名是:chessy_02
---------------------
数组persons2:
姓名是:chessy_02
D'après le résultat, il a été constaté que la valeur en personnes1 a également changé, ce qui est un problème typique de copie superficielle. Le tableau généré par la méthode Arrays.copyOf() est donc une copie superficielle. Dans le même temps, la méthode clone() des tableaux est également la même, et la méthode clone() des collections est également la même, donc lorsque nous utilisons la méthode copy, nous devons faire attention au problème de la copie superficielle.

       有关于深浅拷贝的博文,参考:

      渐析java的浅拷贝和深拷贝:http://www.php.cn/

      使用序列化实现对象的拷贝:http://www.php.cn/

       六、数组转换为List注意地方

       我们经常需要使用到Arrays这个工具的asList()方法将其转换成列表。方便是方便,但是有时候会出现莫名其妙的问题。如下:

public static void main(String[] args) {
        int[] datas = new int[]{1,2,3,4,5};
        List list = Arrays.asList(datas);
        System.out.println(list.size());
    }
------------Output:
1

       结果是1,是的你没有看错, 结果就是1。但是为什么会是1而不是5呢?先看asList()的源码

public static <T> List<T> asList(T... a) {
        return new ArrayList<T>(a);
    }

       注意这个参数:T…a,这个参数是一个泛型的变长参数,我们知道基本数据类型是不可能泛型化的,也是就说8个基本数据类型是不可作为泛型参数的,但是为什么编译器没有报错呢?这是因为在java中,数组会当做一个对象来处理,它是可以泛型的,所以我们的程序是把一个int型的数组作为了T的类型,所以在转换之后List中就只会存在一个类型为int数组的元素了。所以我们这样的程序System.out.println(datas.equals(list.get(0)));输出结果肯定是true。当然如果将int改为Integer,则长度就会变成5了。

       我们在看下面程序:

enum Week{Sum,Mon,Tue,Web,Thu,Fri,Sat}
    public static void main(String[] args) {
        Week[] weeks = {Week.Sum,Week.Mon,Week.Tue,Week.Web,Week.Thu,Week.Fri};
        List<Week> list = Arrays.asList(weeks);
        list.add(Week.Sat);
    }

       这个程序非常简单,就是讲一个数组转换成list,然后改变集合中值,但是运行呢?

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.add(AbstractList.java:131)
    at java.util.AbstractList.add(AbstractList.java:91)
    at com.array.Test.main(Test.java:18)

       编译没错,但是运行竟然出现了异常错误!UnsupportedOperationException ,当不支持请求的操作时,就会抛出该异常。从某种程度上来说就是不支持add方法,我们知道这是不可能的!什么原因引起这个异常呢?先看asList()的源代码:

public static <T> List<T> asList(T... a) {
        return new ArrayList<T>(a);
    }

       这里是直接返回一个ArrayList对象返回,但是注意这个ArrayList并不是java.util.ArrayList,而是Arrays工具类的一个内之类:

private static class ArrayList<E> extends AbstractList<E>
    implements RandomAccess, java.io.Serializable{
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;
        ArrayList(E[] array) {
            if (array==null)
                throw new NullPointerException();
        a = array;
    }
       /** 省略方法 **/
    }

       但是这个内部类并没有提供add()方法,那么查看父类:

public boolean add(E e) {
    add(size(), e);
    return true;
    }
    public void add(int index, E element) {
    throw new UnsupportedOperationException();
    }

       这里父类仅仅只是提供了方法,方法的具体实现却没有,所以具体的实现需要子类自己来提供,但是非常遗憾

这个内部类ArrayList并没有提高add的实现方法。在ArrayList中,它主要提供了如下几个方法:

       1、size:元素数量

       2、toArray:转换为数组,实现了数组的浅拷贝。

       3、get:获得指定元素。

       4、contains:是否包含某元素。

Donc pour résumer, asList renvoie une liste de longueur immuable. Quelle est la longueur du tableau et quelle est la longueur de la liste convertie ? Nous ne pouvons pas augmenter ou diminuer sa longueur en ajoutant ou en supprimant.

Ce qui précède est le contenu du chapitre sur l'amélioration de Java (19) -----Array 2. Pour plus de contenu connexe, veuillez prêter attention à le site PHP chinois (www.php.cn) !


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn