Table des matières
3. Performances ? Veuillez donner la priorité aux tableaux
" >4. Tableau de longueur variable ?
      渐析java的浅拷贝和深拷贝:http://www.php.cn/" >      渐析java的浅拷贝和深拷贝:http://www.php.cn/
      使用序列化实现对象的拷贝:http://www.php.cn/" >      使用序列化实现对象的拷贝:http://www.php.cn/
       六、数组转换为List注意地方" >       六、数组转换为List注意地方
Maison Java javaDidacticiel Chapitre d'amélioration de Java (19) -----Matrice 2

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

Feb 10, 2017 am 11:51 AM
java 数组

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;
    }
Copier après la connexion

 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毫秒
Copier après la connexion


<<> 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);
        }
    }
Copier après la connexion

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 );
    }
}
Copier après la connexion

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
Copier après la connexion
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
Copier après la connexion

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

public static <T> List<T> asList(T... a) {
        return new ArrayList<T>(a);
    }
Copier après la connexion
Copier après la connexion

注意这个参数: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);
    }
Copier après la connexion

这个程序非常简单,就是讲一个数组转换成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)
Copier après la connexion

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

public static <T> List<T> asList(T... a) {
        return new ArrayList<T>(a);
    }
Copier après la connexion
Copier après la connexion

这里是直接返回一个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;
    }
       /** 省略方法 **/
    }
Copier après la connexion

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

public boolean add(E e) {
    add(size(), e);
    return true;
    }
    public void add(int index, E element) {
    throw new UnsupportedOperationException();
    }
Copier après la connexion

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

这个内部类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 de ce site Web
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

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Comment déverrouiller tout dans Myrise
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Racine carrée en Java Racine carrée en Java Aug 30, 2024 pm 04:26 PM

Guide de la racine carrée en Java. Nous discutons ici du fonctionnement de Square Root en Java avec un exemple et son implémentation de code respectivement.

Nombre parfait en Java Nombre parfait en Java Aug 30, 2024 pm 04:28 PM

Guide du nombre parfait en Java. Nous discutons ici de la définition, comment vérifier le nombre parfait en Java ?, des exemples d'implémentation de code.

Générateur de nombres aléatoires en Java Générateur de nombres aléatoires en Java Aug 30, 2024 pm 04:27 PM

Guide du générateur de nombres aléatoires en Java. Nous discutons ici des fonctions en Java avec des exemples et de deux générateurs différents avec d'autres exemples.

Weka en Java Weka en Java Aug 30, 2024 pm 04:28 PM

Guide de Weka en Java. Nous discutons ici de l'introduction, de la façon d'utiliser Weka Java, du type de plate-forme et des avantages avec des exemples.

Numéro de Smith en Java Numéro de Smith en Java Aug 30, 2024 pm 04:28 PM

Guide du nombre de Smith en Java. Nous discutons ici de la définition, comment vérifier le numéro Smith en Java ? exemple avec implémentation de code.

Questions d'entretien chez Java Spring Questions d'entretien chez Java Spring Aug 30, 2024 pm 04:29 PM

Dans cet article, nous avons conservé les questions d'entretien Java Spring les plus posées avec leurs réponses détaillées. Pour que vous puissiez réussir l'interview.

Break or Return of Java 8 Stream Forach? Break or Return of Java 8 Stream Forach? Feb 07, 2025 pm 12:09 PM

Java 8 présente l'API Stream, fournissant un moyen puissant et expressif de traiter les collections de données. Cependant, une question courante lors de l'utilisation du flux est: comment se casser ou revenir d'une opération FOREAK? Les boucles traditionnelles permettent une interruption ou un retour précoce, mais la méthode Foreach de Stream ne prend pas directement en charge cette méthode. Cet article expliquera les raisons et explorera des méthodes alternatives pour la mise en œuvre de terminaison prématurée dans les systèmes de traitement de flux. Lire plus approfondie: Améliorations de l'API Java Stream Comprendre le flux Forach La méthode foreach est une opération terminale qui effectue une opération sur chaque élément du flux. Son intention de conception est

Horodatage à ce jour en Java Horodatage à ce jour en Java Aug 30, 2024 pm 04:28 PM

Guide de TimeStamp to Date en Java. Ici, nous discutons également de l'introduction et de la façon de convertir l'horodatage en date en Java avec des exemples.

See all articles