07-一维数组

07-一维数组

  • 7.1 引言

    • 单个的数组变量可以引用一个大的数据集合。
  • 7.2 数组的基础知识

    一旦数组被创建,他的大小是固定的。使用一个数组引用变量和下标来访问数组中的元素。

    • 7.2.1 声明数组变量
      • 为了在程序中使用数组,必须声明一个引用数组的变量,并指明数组的元素类型。下卖弄是声明数组变量的语法:
        elementType[] arrayRefVar;
        //或者
        elementType arrayRefVar[];//是允许这样的,但是不是最好的方式
        
      • elementType可以是任意数据类型,但是数组中所有的元素都必须具有相同的数据类型。
      • 也可以用elementType arrayRefVar[]声明数组变量。这种来自c/c++语言的风格被Java采纳以适用于c/c++程序员。推荐使用elementType[] arrayRefVar。
    • 7.2.2 创建数组
      • 不同于声明基本数据类型变量,声明一个数组变量时并不给数组分配任何内存空间。它只是创建一个对数组的引用的存储位置。如果变量不包含对数组的引用,那么这个变量的值为null。除非数组已经被创建,否则不能给他分配任何元素。声明数组变量之后,可以使用下面的语法用new操作符创建数组,并且将它的引用赋给一个变量:
        arrayRefVar = new elementType[arraySize];
        
      • 这条语句做了两件事:
        • 1、使用new elementType[arraySize]创建了一个数组;
        • 2、把这个新创建的数组的引用赋值给变量arraySize。
      • 声明一个数组变量、创建数组、将数组引用赋值给变量这三个步骤可以合并在一条语句里。
        elementType[] arrayRefVar = new elementType[arraySize];
        //或者
        elementType arrayRefVar[] = new elementType[arraySize];
        
      • 一个数组变量看起来似乎是存储了一个数组,但实际上他存储的是指向数组的引用。严格的讲,一个数组变量和一个数组是不同的,但多数情况下他们的差别是可以忽略的。因此,为了简化,通常常可以说myList是一个数组,而不用更长的陈述:myList是一个含有double型元素数组的引用变量。
    • 7.2.3 数组大小和默认值
      • 当给数组分配空间时,必须指定该数组能够存储的元素个数,从而确定数组大小。创建数组之后就不能再修改它的大小了。可以使用arrayRefVar.length得到数组的大小。
      • 当创建数组后,他的元素呗赋予默认值,数值型基本数据类型的默认值为0,char型的默认值为‘\u0000’,boolean型的默认值为false。
    • 7.2.4 访问数组元素
      • 数组元素可以通过下标访问。数组下标是基于0的,也就是说,其范围从0开始到arrayRefVar.length-1结束。数组中的每个元素都可以使用下面的语法表示,称为下标变量:
        arrayRefVar[index];
        
    • 7.2.5 数组初始化简写方式
      • Java有一个简捷的标记,称作数组初始化简写方式,他使用下面的语法将声明数组、创建数组和初始化数组结合到一条语句中:
        elementType[] arrayRefVar = {value0,value1,...,valuek};
        
      • 数组初始化简写方式中不使用操作符new。使用数组初始化简写方式时,必须将声明、创建和初始化数组都放在一条语句中。
    • 7.2.6 处理数组
      • 处理数组元素时,经常会用到for循环,理由如下:
        • 数组中所有元素都是同一类型的。可以使用循环以同样的方式反复处理这些元素。
        • 由于数组的大小是已知的,所以很自然的就使用for循环。
      • 1、使用输入值初始化数组
        double[] myList = new double[4];
                java.util.Scanner input = new java.util.Scanner(System.in);
                System.out.print("Enter " + myList.length + " values: ");
                for (int i = 0;i < myList.length;i++)
                    myList[i] = input.nextDouble();
        
      • 2、使用随机数初始化数组
        for (int i = 0;i < myList.length;i++){
                    myList[i] = Math.random() * 100;
                }
        
      • 3、显示数组
        char[] city = {'D','a','l','l','a','s'};
                System.out.println(city);
        
      • 4、对所有元素求和
        double total = 0;
                for (int i = 0;i < myList.length;i++){
                    total += myList[i];
                }
        
      • 5、找出最大元素
        double max = myList[0];
                for (int i = 0;i < myList.length;i++){
                    if (myList[i] > max)max = myList[i];
                }
        
      • 6、找出最大元素的最小下标值
        double max = myList[0];
                int indexOfMax = 0;
                for (int i = 1;i < myList.length;i++){
                    max = myList[i];
                    indexOfMax = 1;
                }
        
      • 7、随机打乱
        for (int i = 0;i < myList.length - 1;i++){
                    int j = (int)(Math.random() * myList.length);
                    double temp = myList[i];
                    myList[i] = myList[j];
                    myList[j] = temp;
                }
        
      • 8、移动元素
        double temp = myList[0];
                for (int i = 1;i < myList.length;i++){
                    myList[i - 1] = myList[i];
                }
                myList[myList.length - 1] = temp;
        
      • 9、简化编码
        String[] months = {"January","Februry",....,"December"};
                System.out.print("Enter a month number (1 to 12): ");
                int monthNumber = input.nextInt();
                System.out.println("The month is " + months[monthNumber - 1]);
        
    • 7.2.7 foreach循环
      • Java支持一个简便的for循环,称为foreach循环,即不使用下标变量就可以顺序的遍历整个数组。下面的代码就可以显示数组myList的所有元素:
        for(double e : myList){
            Syetem.out.println(e)
        }
        
      • foreachde的语法是:
        for(elementType element: arrayRefVar){
        //Process the element
        }
        
  • 7.3 示例学习:分析数字

    • 编写一个程序,找到大于平均值的项的数目。
      package chapter06;
      
      public class AnalyzeNumbers {
          public static void main(String[] args){
              java.util.Scanner input = new java.util.Scanner(System.in);
              System.out.print("Enter the number of items: ");
              int n = input.nextInt();
              double[] numbers = new double[n];
              double sum = 0;
              
              System.out.print("Enter the numbers : ");
              for (int i = 0;i < n;i++){
                  numbers[i] = input.nextDouble();
                  sum += numbers[i];
              }
              
              double average = sum / n;
              
              int count = 0;
              for (int i = 0;i < n;i++)
                  if (numbers[i] > average)
                      count++;
                  
              System.out.println("Average is " + average);
              System.out.println("Number of elements above the average is " + count);
          }
      }
      
      
  • 7.4 示例学习:一副牌

    package chapter06;
    
    public class DeckOfCards {
        public static void main(String[] args){
            int[] deck = new int[52];
            String[] suits = {"Spads","Hearts","Diamonds","clubs"};
            String[] ranks = {"Ace","2","3","4","5","6","7","8","9","10","Jack","Queen","King"};
            
            for (int i = 0;i < deck.length;i++)
                deck[i] = i;
            
            for (int i = 0;i < deck.length;i++){
                int index = (int)(Math.random() * deck.length);
                int temp = deck[i];
                deck[i] = deck[index];
                deck[index] = temp;
            }
            
            for (int i = 0;i < 4;i++){
                String suit = suits[deck[i] / 13];
                String rank = ranks[deck[i] % 13];
                System.out.println("Card number " + deck[i] + ": " + rank + " of " + suit);
            }
        }
    }
    
    
  • 7.5 复制数组

    • 要将一个数组中的内容复制到另外一个数组中,需要将数组的每个元素复制到另外一个数组中。
      list2 = list1
      
    • 上面的语句并不能将list1引用的数组内容复制到list2,而只是将list1的引用值复制给了list2.在这条语句之后,list1和list2都指向同一个数组。list2原先所引用的数组不能再引用,它就变成了垃圾,会被Java虚拟机自动收回(这个过程称为垃圾回收)。
    • 复制数组有三种方法:
      • 1、使用循环语句逐个的赋值数组的元素;
      • 2、使用System类中的静态方法arraycopy;
        • arraycopy的语法是:
          arraycopy(sourceArray,srcPos,targeArray,tarPos,length);
          
        • 参数srcPos和tarPos分别表示在源数组sourceArray和目标数组targetArray中的起始位置。从sourceArray复制到targetArray中的元素个数由参数length指定。
        • arraycopy方法没有给目标数组分配内存空间。复制前必须创建目标数组以及分配给他的内存空间。复制完成后,sourceArray和targetArray具有相同的内容,但占有独立的内存空间。
      • 3、使用clone方法赋值数组。
  • 7.6 将数组传递给方法

    • 当一个数组传递给方法时,数组的引用被传给方法。
    • 和方法传递基本数据类型一样,也可以给方法传递数组。
      public static void printArray(int[] array){
          for(int i = 0;i < array.length;i++){
              System.out.print(array[i] + " ");
          }
      }
      
    • 使用下述语法创建数组:
      new elementType[]{value0,value1,...,valuek};
      
    • 该数组没有显式的引用变量,这样的数组称为匿名函数。
    • Java使用按值传递的方式将实参传递给方法。传递剧本数据类型变量的值与传递数组值有很大的不同:
      • 对于基本数据类型参数,传递的是实参的值;
      • 对于数组类型参数,参数值是数组的引用,给方法传递的是这个引用。从语义上来讲,最好的描述为传递共享信息,即方法中的数组和传递的数组是一样的。因此,如果改变方法中的数组,将会看到方法外的数组也改变了。
        package chapter06;
        
        public class TestPassArray {
            public static void main(String[]  args){
                int[] a = {1,2};
                
                System.out.println("Before invoking swap");
                System.out.println("array is {" + a[0] + ", " + a[1] + "}");
                swap(a[0],a[1]);
                System.out.println("After invoking swap");
                System.out.println("array is {" + a[0] + ", " + a[1] + "}");
            }
            public static void swap(int n1,int n2){
                int temp = n1;
                n1 = n2;
                n2 = temp;
            }
            public static void swapFirstTwoInArray(int[] array){
                int temp = array[0];
                array[0] = array[1];
                array[1] = temp;
            }
        }
        
        
  • 7.7 方法返回数组

    • 当方法返回一个数组时,数组的引用被返回。
  • 7.8 示例学习:统计每个字母出现的次数

    package chapter06;
    
    public class CountLettersInArray {
        public static void main(String[] args){
            char[] chars = createArray();
            
            System.out.println("The lowercase letters are: ");
            displayArray(chars);
            
            int[] counts = countLetters(chars);
            
            System.out.println();
            System.out.println("The occurrences of each letter are: ");
            displayCounts(counts);
        }
        public static char[] createArray(){
            char[] chars = new char[100];
            for (int i = 0;i < chars.length;i++)
                chars[i] = RandomCharacter.getRandomLowerCaseLetter();
            return chars;
        }
        public static void displayArray(char[] chars){
            for (int i = 0;i < chars.length;i++){
                if ((i + 1) % 20 == 0)
                    System.out.println(chars[i]);
                else 
                    System.out.println(chars[i] + " ");
            }
        }
        public static int[] countLetters(char[] chars){
            int[] counts = new int[26];
            for (int i = 0;i < chars.length;i++)
                counts[chars[i] - 'a']++;
            return counts;
        }
        public static void displayCounts(int[] counts){
            for (int i = 0;i < counts.length;i++){
                if ((i + 1) % 10 == 0)
                    System.out.println(counts[i] + " " + (char)(i + 'a'));
                else 
                    System.out.println(counts[i] + " " + (char)(i + 'a') + " ");
            }
        }
    }
    
    
  • 7.9 可变长参数列表

    • 具有同样类型的数目可变的参数可以传递给方法,并将作为数组对待。方法中的参数声明如下:
      typeName...patameterName(类型名...参数名)
      
    • 在方法声明中,指定类型后紧跟着省略号(...)。只能个方法中指定一个可变长参数,同时该参数必须是最后一个参数。任何常规参数必须在他之前。
    • Java将可变长参数当成数组对待。
      package chapter06;
      
      public class VarArgsDemo {
          public static void main(String[] args){
              
          }
          public static void printMax(double...numbers){
              if (numbers.length == 0){
                  System.out.println("No argument passed");
                  return;
              }
              
              double result = numbers[0];
              
              for (int i = 1;i < numbers.length;i++)
                  if (numbers[i] > result)
                      result = numbers[i];
                  
               System.out.println("The max value is " + result);
          }
      }
      
      
  • 7.10 数组的查找

    • 7.10.1 线性查找法
      package chapter06;
      
      public class LineearSearch {
          public static int linearSearch(int[] list,int key){
              for (int i = 0;i < list.length;i++){
                  if (key == list[i])
                      return i;
              }
              return -1;
          }
      }
      
      
    • 7.10.2 二分查找法
      package chapter06;
      
      public class BinarySearch {
          public static int binarySearch(int[] list,int key){
              int low = 0;
              int high = list.length - 1;
              
              while (high >= low){
                  int mid = (low + high) / 2;
                  if (key < list[mid])
                      high = mid - 1;
                  else if (key == list[mid])
                      return mid;
                  else 
                      low = mid + 1;
              }
              return -low + 1;
          }
      }
      
      
    • 二分查找法的前提是列表必须以升序排好序了。
  • 7.11 数组的排序

    package chapter06;
    
    public class SelectionSort {
        public static void selectiongSort(double[] list){
            for (int i = 0;i < list.length;i++){
                double currentMin = list[i];
                int currentMinIndex = 1;
                
                for (int j = i + 1;j < list.length;j++){
                    if (currentMin > list[j]){
                        currentMin = list[j];
                        currentMinIndex = j;
                    }
                }
                if (currentMin != 1){
                    list[currentMinIndex] =list[i];
                    list[i] = currentMin;
                }
            }
        }
    }
    
    
  • 7.12 Arrays类

    • java.util.Arrays类包含一些使用的方法用于常见的数组操作,比如排序和查找。
    • 可以使用sort或者parrallelSort方法对整个数组或部分数组进行排序。
    • 可以调用sort(number)对整个数组numbers排序。可以调用sort(chars,1,3)对从chars[1]到chars[3-1]的部分数组进行排序。如果你的计算机有多个处理器,那么parallelSort将更加高效。
              double[] numbers = {6.0,4.4,1.9,2.9,3.4,3.5};
              java.util.Arrays.sort(numbers);
              java.util.Arrays.parallelSort(numbers);
              
              char[] chars = {'a','A','4','F','D','P'};
              java.util.Arrays.sort(chars,1,3);
              java.util.Arrays.parallelSort(chars,1,3);
      
    • 可以采用二分查找法(binarySearch方法)在数组中查找关键字。如果数组中不存在关键字,方法返回-(insertIndex+1)。
              int[] list = {2,4,7,10,11,45,50,59,60,66,69,70,79};
              System.out.println("1. Index is " + java.util.Arrays.binarySearch(list,11));
              System.out.println("2. Index is " + java.util.Arrays.binarySearch(list,12));
              
              char[] chars1 = {'a','c','g','x','y','z'};
              System.out.println("3.Index is " + java.util.Arrays.binarySearch(chars,'a'));
              System.out.println("4.Index is " + java.util.Arrays.binarySearch(chars,'t'));
      
    • 可以采用equals方法检测两个数组是否严格相等。
              int[] list1 = {2,4,7,10};
              int[] list2 = {2,4,7,10};
              int[] list3 = {4,2,7,10};
              System.out.println(java.util.Arrays.equals(list1,list2));//true
              System.out.println(java.util.Arrays.equals(list2,list3));//false
      
    • 可以使用fill方法填充整个数组或部分数组。
      int[] list1 = {2,4,7,10};
              int[] list2 = {2,4,7,7,7,10};
              java.util.Arrays.fill(list1,5);
              java.util.Arrays.fill(list2,1,5,8);
      
    • 可以使用toString方法来返回一个字符串,该字符串代表了数组中的所有元素。
      int[] list3 = {2,4,7,10};
              System.out.println(java.util.Arrays.toString(list));
      
  • 7.13 命令行参数

    main方法的生命有点特殊,他具有String[]类型参数args。很明显,参数args是一个字符串数组。main方法就像一个带参数的普通方法。可以通过传递实参来调用一个普通方法。当然也是可以给main传递参数的。

    • 7.13.1 向main方法传递字符串
      • 运行程序时,可以从命令行给main方法传递字符串参数。例如,爱你的命令行用三个字符串arg0、arg1、arg2启动程序TestMain:
        java TestMain arg0 arg1 arg2
        
      • 其中,参数arg0、arg1、arg2都是字符串,但是在命令行中出现时,不需要放在双引号中。这些字符串用空格分隔。如果字符串包含空格,那就必须使用双引号括住。
      • 当调用main方法时,Java解释器会创建一个数组存储命令行参数,然后将该数组的引用传递给args。例如,乳沟调用具有n个参数的程序,Java解释器创建一个如下所示的数组:
        args = new String[n];
        
      • 如果运行程序时没有传递字符串,那么使用new String[0]创建数组。在这种情况下,哎数组是长度为0的空数组。args是对这个空数组的引用。因此,args不是null,args.length为0。
    • 7.13.2 示例学习:计算器
      package chapter06;
      
      public class Calculator {
          public static void main(String[] args){
              if (args.length != 3){
                  System.out.println("Usage:java Calculator operand1 operator operand2");
                  System.exit(1);
              }
              
              int result = 0;
              
              switch (args[1].charAt(0)){
                  case '+':result = Integer.parseInt(args[0]) + Integer.parseInt(args[2]);break;
                  case '-':result = Integer.parseInt(args[0]) - Integer.parseInt(args[2]);break;
                  case '.':result = Integer.parseInt(args[0]) * Integer.parseInt(args[2]);break;
                  case '/':result = Integer.parseInt(args[0]) / Integer.parseInt(args[2]);break;
              }
              System.out.println(args[0] + ' ' + args[1] + ' ' + args[2] + " = " + result);
          }
      }
      
      
      • 我们使用.符号用于乘法,而不是通常的符号。原因是当符号用于命令行时表示当前目录下的所有文件。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342