Résumé :
Cet article explique principalement les connaissances sur les tableaux en Java, principalement Les tableaux seront abordés en détail sous cinq aspects : les tableaux et les conteneurs, la création et l'initialisation des tableaux, les tableaux et les génériques, les tableaux et les paramètres variableslistes, et les fonctions pratiques des classes d'outils de Array Description et résumé.
Tableaux et conteneurs
Création et création des tableaux Initialisation
Tableaux et génériques
Tableaux et listes de paramètres variables
Classe d'outils Tableaux Résumé des fonctions pratiques
En Java, les tableaux et les conteneurs Vous peut contenir des objets , alors quelle est la différence entre les tableaux et les conteneurs ? Lorsque nous devons contenir des objets, dans quelles circonstances devons-nous donner la priorité aux tableaux et dans quelles circonstances devons-nous donner la priorité aux conteneurs ?
Dans la version initiale de Java, les tableaux de taille fixe étaient absolument nécessaires, non seulement parce que les concepteurs Java ont choisi d'inclure des types primitifs dans Java et certaines considérations basées sur les performances, mais aussi à cause de la version initiale a très peu de support pour les conteneurs. Par conséquent, dans les premières versions de Java, il est toujours raisonnable de choisir d'inclure des tableaux, notamment dans les trois aspects suivants :
Efficacité
En Java, Les tableaux sont le moyen le plus efficace de stocker et d'accéder de manière aléatoire à des séquences d'objetsréférences. Un tableau est une séquence linéaire simple, qui rend l’accès aux éléments très rapide. Cependant, le prix payé pour cette vitesse est que la taille de l'objet tableau est fixe et ne peut pas être modifiée pendant sa durée de vie. Étant donné qu'ArrayList peut réaliser une allocation automatique d'espace et est plus flexible, nous devrions généralement préférer ArrayList au tableau, mais cette flexibilité nécessite une surcharge. Par conséquent, ArrayList est beaucoup moins efficace que les tableaux.
Type
Avant JDK 1.5, Java n'introduisait pas de génériques. Par conséquent, lors de la manipulation d'objets, les classes de conteneurs avant les génériques les traitent comme n'ayant pas de type spécifique, c'est-à-dire que ces objets sont traités comme des Object. La raison pour laquelle les tableaux sont meilleurs que les conteneurs avant les génériques est que vous pouvez créer un tableau pour contenir un type spécifique. Cela signifie que vous pouvez empêcher l'insertion de types incorrects et l'extraction de types inappropriés via la vérification de type au moment de la compilation. Bien sûr, Java vous empêchera d'envoyer des messages inappropriés aux objets, à la fois au moment de la compilation et au moment de l'exécution. Ce n'est donc pas celle qui est la moins sûre, mais elle sera plus élégante si des erreurs peuvent être signalées lors de la compilation.
La possibilité de sauvegarder les types de base
Les tableaux peuvent contenir des types de base, mais les conteneurs avant les génériques ne le peuvent pas.
Après JDK 1.5, Java a introduit les génériques et les mécanismes d'empaquetage automatiques (les génériques peuvent assurer la production de conteneurs de type sécurisé, et les mécanismes d'empaquetage automatiques permettent aux conteneurs de contenir des types de base), ce qui fait que les conteneurs d'aujourd'hui éclipsent les tableaux dans tous les aspects, à l'exception des performances. De plus, les génériques sont une grande menace pour les tableaux, et généralement les deux ne peuvent pas être bien combinés (les tableaux avec des types paramétrés ne peuvent pas être instanciés) .
Par conséquent, lorsque nous programmons en utilisant des versions Java récentes , devrait préférer les conteneurs aux tableaux. Nous devrions refactoriser notre programme pour utiliser des tableaux uniquement s'il a été prouvé que les performances sont un problème et que le passage aux tableaux améliorera les performances.
1. Bases du tableau
L'identifiant du tableau est juste un référence , pointant vers un objet réel créé dans le tas. Cet objet est utilisé pour enregistrer des références à d'autres objets ou valeurs de types de base
les tableaux d'objets enregistrent les références et le type de base. tableaux directement Enregistrer les valeurs de type de base ;
La syntaxe "[ ]" est le seul moyen d'accéder aux objets du tableau ;
2. Créer et initialiser
est implicitement créé dans le cadre de l'initialisation du tableau
String[] strs = { ... }; // 创建方式 1 --- 花括号内对象的个数就是数组大小System.out.println(strs.length); // 输出 0
Créer explicitement en utilisant nouvelle expression
String[] strs = new String[5]; //创建方式 2String[] ss = new String[]{ ... }; //创建方式 3
L'essence du tableau multidimensionnel : Les éléments du tableau sont toujours des tableaux
// 创建方式 1int[][] a = { { 1, 2, 3, }, { 4, 5, 6, }, }; // 创建方式 2int[][][] a = new int[2][2][4];//粗糙数组:每个向量具有任意长度Random rand = new Random(47); // 3-D array with varied-length vectors: int[][][] a = new int[rand.nextInt(7)][][]; for(int i = 0; i < a.length; i++) { a[i] = new int[rand.nextInt(5)][]; for(int j = 0; j < a[i].length; j++) a[i][j] = new int[rand.nextInt(5)]; }
Les tableaux et les génériques ne peuvent pas être bien combinés, c'est-à-dire qu'ils ne peuvent pas l'être. instancié avec paramétrage Tableau de type
T[] first = new T[3]; // ERROR A<String>[] arrays = new A<String>[4]; // ERROR: Cannot create a generic array of A<String>
peut créer une référence de tableau générique
A<String>[] arrays; // OK
Les tableaux sont covariants
Object[] objs = new String[3]; // OK
En bref, Les conteneurs génériques sont toujours un meilleur choix que les tableaux génériques.
1. Le concept de types de paramètres variables
Java SE5 ajoute des types de paramètres variables (Variable Argument Type), sous la forme de "Type... args", ne peut être utilisé que comme paramètres de méthode . La liste des paramètres variables convient aux situations où le nombre de paramètres est incertain mais le type est certain (java traite les paramètres variables comme un tableau). Une attention particulière doit être portée au fait que la liste des paramètres variables doit être le dernier élément (c'est-à-dire qu'un seul paramètre variable est pris en charge au maximum). Lorsqu'il y a plus d'une liste de paramètres variables, l'une des variables ne doit pas être le dernier élément, donc un seul paramètre variable est pris en charge. Étant donné que le nombre de paramètres dans la liste des paramètres variables est incertain, lorsqu'il y a des paramètres du même type derrière, Java ne peut pas distinguer si le paramètre transmis appartient au paramètre variable précédent ou au paramètre suivant, il ne peut donc placer que le paramètre variable. à la fin. Un élément.
// 代码示例public class TestVarArgus { public static void dealArray(int... intArray){ for (int i : intArray) System.out.print(i +" "); System.out.println(); } public static void main(String args[]){ dealArray(); dealArray(1); dealArray(1, 2, 3); } }/* Output: 1 1 2 3 *///:~
La liste des paramètres des variables a les caractéristiques suivantes :
ne peut apparaître qu'à la fin de la liste des paramètres de la méthode ;
… se trouve dans le type variable et le nom de la variable peut être avec ou sans espaces
Lors de l'appel de la méthode avec des paramètres variables, le compilateur will Le paramètre variable crée implicitement un tableau, nous pouvons donc accéder à la liste des paramètres variables sous la forme d'un tableau dans le corps de la méthode (le compilateur traite le paramètre variable comme un tableau) .
2. Compatibilité des types de paramètres variables et des tableaux
Le compilateur considère que le type de tableau et le type de paramètre variable sont identiques, c'est-à-dire qu'ils ne peuvent pas surcharger
public class TestVarArgus { public static void dealArray(int... intArray){ for (int i : intArray) System.out.print(i +" "); System.out.println(); } //ERROR : Duplicate method dealArray(int[]) in type TestVarArgus public static void dealArray(int[] intArray){ for (int i : intArray) System.out.print(i +" "); System.out.println(); } public static void main(String args[]){ dealArray(); dealArray(1); dealArray(1, 2, 3); } }
Les paramètres variables sont compatibles avec les paramètres de type tableau, mais les paramètres de type tableau ne sont pas compatibles avec les paramètres variables
// 代码示例 1 : 给参数为可变参数类型的方法传递数组public class TestVarArgus { public static void dealArray(int... intArray){ for (int i : intArray) System.out.print(i +" "); System.out.println(); } public static void main(String args[]){ int[] intArray = {1, 2, 3}; dealArray(intArray); // OK } }
// 代码示例 2 : 给参数为数组类型的方法传递可变参数public class TestVarArgus { public static void dealArray(int[] intArray){ for (int i : intArray) System.out.print(i +" "); System.out.println(); } public static void main(String args[]){ dealArray(1, 2, 3); // ERROR } }
donnera la priorité à correspondant à cette méthode ;
public class TestVarArgus { //含有不定参数的那个重载方法是最后被选中的public static void dealArray(int... intArray){ System.out.println("Bad"); } public static void dealArray(int count, int count2){ System.out.println("Bingo"); } public static void main(String args[]){ dealArray(1, 2); } } /* Output: Bingo *///:~
fonction Le paramètre peut également être réécrit en un type de paramètre variable : public static void main(String... args) .
Function | Introduction | Note |
---|---|---|
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length) | 从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束 | 若复制对象数组,那么只是复制了对象的引用,而不是对象本身的拷贝(浅复制);该方法不会执行自动包装和自动拆包,所以两个数组必须具有相同的确切类型;须明确自行新建立一个数组对象,作为副本 |
copyOf(T[] original, int newLength) | 复制指定的数组,截取或用 null 填充 | 底层调用的还是 System.arraycopy;返回一个新的数组对象,若新数组的长度超过原数组的长度,则保留数组默认值 |
注意:
对于以上两个方法:
若复制对象数组,那么只是复制了对象的引用,而不是对象本身的拷贝;
这两个方法不会执行自动包装和自动拆包,所以两个数组必须具有相同的确切类型。
2、数组的字符串方式表示
方法: Arrays.toString(Object[] a) / Arrays.deepToString(Object[] a)
作用: 返回指定数组内容的字符串表示形式:前者适用于一维数组,或者适用于多维数组
3、数组的比较
方法: Arrays.equals(Object[] a, Object[] a2) / deepEquals(Object[] a1, Object[] a2) (多维)
作用: 比较两个数组:元素类型相同,元素个数相等,对应位置的元素相同;
注意:
通过对每个元素使用 equals() 作比较来判断;
对于基本类型,使用的是基本类型的包装器类的 equals() 方法(对于 int 类型使用 Integer.equals() 作比较);
使用 equals() 方法比较原则:是不是同一个对象,是不是同一个类型,是不是具有相同的内容。
int[] a1 = new int[10]; int[] a2 = new int[10]; Arrays.fill(a1, 47); Arrays.fill(a2, 47); print(Arrays.equals(a1, a2)); //true
4、数组的排序
使用内置的排序方法,就可以对任意的基本类型数组排序;也可以对任意的对象数组进行排序,只要该对象实现了 Comparable 接口或具有相关联的 Comparator (独立的实现该接口的类)。
方法: Arrays.sort(Object[] a) / Arrays.sort(Object[] a, int fromIndex, int toIndex)
Arrays.sort(T[] a, Comparator super T> c) / Arrays.sort(T[] a, int fromIndex, int toIndex, Comparator super T> c)
作用: 对数组内元素进行升序排序 (默认)
String[] sa = Generated.array(new String[20], new RandomGenerator.String(5)); // 利用 String 内置的比较器(已实现 Comparable 接口):字典序(大写字母开头的词都放在前面输出,之后才是小写字母开头的词)Arrays.sort(sa); // ... ,WHkjU, YNzbr, bkIna, cQrGs, .... // 利用 Comparator 比较 : Collections.reverseOrder() : 现有顺序的逆序Arrays.sort(sa, Collections.reverseOrder()); // 利用 Comparator 比较 : String.CASE_INSENSITIVE_ORDER : 忽略大小写将单词一起进行排序Arrays.sort(sa, String.CASE_INSENSITIVE_ORDER);
Java 标准类库中的排序算法针对正排序的特殊类型进行了优化 ———— 针对基本类型设计的“快排” 和 针对对象设计的“稳定归并排序”。所以,无需担心排序的性能,除非你可以证明排序部分的确是程序效率的瓶颈。
5、在已排序的数组中查找
若数组已经 排好序,就可以使用该方法执行快速查找;若对未排序的数组使用该方法,将产生不可预料的结果。
方法: binarySearch(Object[] a, Object key) / binarySearch(T[] a, T key, Comparator super T> c)
作用: 使用 二分搜索法 来搜索指定数组,以获得指定对象。在进行此调用之前,必须根据元素的自然顺序对数组进行升序排序(通过 sort(Object[]) 方法); 使用二分搜索法来搜索指定数组,以获得指定对象。在进行此调用之前,必须根据指定的比较器(通过 sort(T[], Comparator) 方法)对数组进行多态升序排序。
注意:
对 已经有序 的数组进行查找;
Si la cible est trouvée, la valeur renvoyée par la méthode n'est pas inférieure à 0 ; sinon, la valeur de retour négative qu'elle génère indique la position qui doit être insérée sous ce tri ; 🎜>
"sort(Object[])" correspond à "binarySearch(Object[] a, Object key)", "sort(T[], Comparator)" correspond à binaireSearch(T[] a, T key, Comparator super T> c) Correspond.
Si le tableau contient des éléments en double, cette méthode ne peut pas garantir quel élément est trouvé ; si vous devez trier un tableau sans éléments en double, vous pouvez utiliser Tree Set ; (maintenir l'ordre de tri) ou LinkedHashSet (maintenir l'ordre d'insertion) pour le tri. Il n'est pas nécessaire de maintenir les baies vous-même à moins qu'elles ne deviennent un goulot d'étranglement dans votre programme.
Méthode : fill(Object[] a, Object val)
Fonction : ne peut remplir chaque position qu'avec la même valeur, et pour les objets, il s'agit de copier la référence du même objet à remplir
Méthode : asList(T… a)
Fonction : Renvoie un Liste de taille fixe prise en charge par le tableau spécifié
Remarque :
La représentation sous-jacente est le tableau et ne peut donc pas être redimensionnée. Par conséquent, l'appel de la méthode add/remove lancera java.lang.UnsupportedOperationException (opération facultative).
Arrays.asList() consiste en réalité à : transmettre son résultat en tant qu'argument constructeur à n'importe quelle collection (ou utiliser addAll méthode, Collections.addAll static méthode), qui peut générer un conteneur dynamique.
Principes :
Préférez utiliser des conteneurs plutôt que des tableaux
Utilisez des tableaux et des paramètres variables lors de la création paramètres de méthode, donner la priorité à l'utilisation de paramètres variables rendra le programme plus découplé. Obtenez deux fois le résultat avec la moitié de l'effort de programmation ;
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!