1. 数组的声明和创建
语法为:
elementType[] arrayRefVar;
例如:
int[] myList;
写成与C/C++兼容的形式int myList[]
也是可以的, 但在Java中写成int[] myList
是首选。
// 声明数组变量 myList, 创建数组,并将数组引用赋给变量
double[] myList = new double[10];
数组的初始化
声明,创建以及初始化3合1,语法:
elementType[] arrayRefVar = {value0, value1, ..., valuek};
例子:
double[] myList = {1.9, 2.9, 3.4, 3.5};
等价于:
double[] myList = new double[4];
myList[0] = 1.9;
myList[1] = 2.9;
myList[2] = 3.4;
myList[3] = 3.5;
2. 处理数组
1.用输入值初始化数组
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.用随机值初始化数组
Math.random()
的范围:[0.0, 1.0)
for (int i = 0; i < myList.length; i++) {
myList[i] = Math.random() * 100;
}
3.显示数组
for (int i = 0; i < myList.length; i++) {
System.out.print(myList[i] + " ");
}
char[] city = {'D', 'a', 'l', 'l', 'a', 's'}; //字符数组, 下行写数组名就可以
System.out.println(city); //输出: "Dallas"
4.寻找最大元素的最小索引
double max = myList[0];
int indexOfMax = 0;
for (int i = 1; i < myList.length; i++) {
if (myList[i] > max) {
max = myList[i];
indexOfMax = i;
}
}
5.随机洗牌
for (int i = myList.length – 1; i > 0; i––) {
// Generate an index j randomly with 0 <= j <= i
int j = (int)(Math.random() * (i + 1));
// Swap myList[i] with myList[j]
double temp = myList[i];
myList[i] = myList[j];
myList[j] = temp;
}
6.移动元素
// Shift elements left
for (int i = 1; i < myList.length; i++) {
myList[i - 1] = myList[i];
}
// Move the first element to fill in the last position
myList[myList.length - 1] = temp;
Foreach 循环
可以用下面的语法遍历数组:
for (elementType element: arrayRefVar) {
// Process the element
}
例如遍历 myList
:
for (double e: myList) {
System.out.println(e);
}
Python的语法比这更为简洁。
例子:打印大于平均数的个数
package testarray;
public class TestArray {
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];
int counts = 0;
double sum = 0;
System.out.print("Enter these numbers: ");
for (int i = 0; i < n; i++) {
numbers[i] = Input.nextDouble();
sum += numbers[i];
}
double average = sum / n;
for (int i = 0; i < n; i++) {
if (numbers[i] > average)
counts++;
}
System.out.println("The average is: " + average);
System.out.println("The number of items above average is " + counts);
}
}
3. 复制数组
复制数组不能直接变量划等号:
double[] list1 = {1, 2, 3};
double[] list2 = {4, 5, 6};
list2 = list1; // Cannot copy array!
list2 = list1
的结果就是,list1
和 list2
都引用相同的数组,list2
原先引用的数组变为垃圾,将由JVM自动回收。如此赋值不能实现数组复制。
实现数组复制有3种方法:
1. 数组元素逐个复制
2. 使用System
类中的静态arraycopy
方法:
arraycopy(sourceArray, srcPos, targetArray, tarPos, length);
3. 使用clone
方法(涉及到抽象类和接口)
4. 将数组传递给方法
当传递数组给方法时,实际传递的是数组的引用。
匿名数组
public static void printArray(int[] array) {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
}
调用该方法时,可以使用:
printArray(new int[] {1, 2, 3, 4, 5});
使用语法new elementType[]{value0, value1, ..., valuek}
创建的数组叫做匿名数组。
Java 使用 pass-by-value
的方式传递参数给方法,传递原生数据类型的值和传递数组之间有着重要的区别:
1. 对于原生类型参数,传递参数的值
2. 对于数组类型参数,参数的值为对数组的引用,此引用值被传递给方法。语义上说,最好描述为 pass-by-sharing, 也就是说,方法中的数组同被传递的数组,因此,如果在方法中改变数组,你可以看到在方法外的数组也被修改了。
Java 中,数组是对象,JVM将对象存在堆内存中。
5. 从方法返回数组
当方法返回数组时,返回的实际上是数组的引用。
反转数组的一个例子:
public static int[] reverse(int[] list) {
int[] result = new int[list.length];
for (int i = 0, j = result.length - 1; i < list.length; i++, j--)
{
result[j] = list[i];
}
return result;
}
对这个方法的调用如下:
int[] list1 = {1, 2, 3, 4, 5, 6};
int[] list2 = reverse(list1);
例子:统计每个字母出现的次数
给定一个随机字符的数组,长度100, 统计每个字母出现的次数:
// FILENAME: RandomCharacter.java
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package testarray;
/**
*
* @author
*/
public class RandomCharacter {
/** Generate a random character between ch1 and ch2 */
public static char getRandomCharacter(char ch1, char ch2) {
return (char)(ch1 + Math.random() * (ch2 - ch1 + 1));
}
/** Generate a random lowercase letter */
public static char getRandomLowerCaseLetter() {
return getRandomCharacter('a', 'z');
}
/** Generate a random uppercase letter */
public static char getRandomUpperCaseLetter() {
return getRandomCharacter('A', 'Z');
}
/** Generate a random digit character */
public static char getRandomDigitCharacter() {
return getRandomCharacter('0', '9');
}
/** Generate a random character */
public static char getRandomCharacter() {
return getRandomCharacter('\u0000', '\uFFFF');
}
}
// FILENAME: TestArray.java
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package testarray;
public class TestArray {
public static void main(String[] args) {
// Declare and create an array
char[] chars = createArray();
// Display the array
System.out.println("The lowercase letters are:");
displayArray(chars);
// Count the occurrences of each letter
int[] counts = countLetters(chars);
// Display counts
System.out.println();
System.out.println("The occurrences of each letter are:");
displayCounts(counts);
}
/** Create an array of characters */
public static char[] createArray() {
// Declare an array of characters and create it
char[] chars = new char[100];
// Create lowercase letters randomly and assign
// them to the array
for (int i = 0; i < chars.length; i++)
chars[i] = RandomCharacter.getRandomLowerCaseLetter();
// Return the array
return chars;
}
/** Display the array of characters */
public static void displayArray(char[] chars) {
// Display the characters in the array 20 on each line
for (int i = 0; i < chars.length; i++) {
if ((i + 1) % 20 == 0)
System.out.println(chars[i]);
else
System.out.print(chars[i] + " ");
}
}
/** Count the occurrences of each letter */
public static int[] countLetters(char[] chars) {
// Declare and create an array of 26 int
int[] counts = new int[26];
// For each lowercase letter in the array, count it
for (int i = 0; i < chars.length; i++)
counts[chars[i] - 'a']++;
return counts;
}
/** Display 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.print(counts[i] + " " + (char)(i + 'a') + " ");
}
}
}
运行结果:
The lowercase letters are:
x l w s j e p k n k c t b t c j e c u y
l j r k j j c i o c k s n t i d p a a v
y o a b y p a w o f i a w t z d r c h a
a j o g e g q m w w o g d u p g x u m z
j q c m j p a w n k i t s q s t c g l u
The occurrences of each letter are:
8 a 2 b 8 c 3 d 3 e 1 f 5 g 1 h 4 i 8 j
5 k 3 l 3 m 3 n 5 o 5 p 3 q 2 r 4 s 6 t
4 u 1 v 6 w 2 x 3 y 2 z 成功生成(总时间:0 秒)
6. 可变长度参数列表
相同类型的可变数目的参数可以传给方法,并看作一个数组。
方法的可变长度参数声明形式为:typeName... parameterName
例如:public static void printMax(double... numbers)
, 一个方法里最多只能有一个可变长度的参数,而且必须是最后一个参数,一般的参数排列靠前。
输出最大值的例子:
package testarray;
public class TestArray {
public static void main(String[] args) {
printMax(34, 3, 3, 2, 56.5);
printMax(new double[]{1, 2, 3});
printMax(1, 2, 2, 1, 4);
printMax(new double[]{1, 2, 3});
//printMax(new int[]{1, 2, 3}); // 错误:required double[], found int[]
}
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);
}
}
输出:
run:
The max value is 56.5
The max value is 3.0
The max value is 4.0
The max value is 3.0
成功生成(总时间:0 秒)
7. 数组查找
介绍了两种,线性查找和二进制查找,线性查找直观,二进制要先排序,但查找速度快。
8. 数组排序
选择排序算法,省略
9. Array
类
java.util.Arrays
类含有用于一般数组操作的有用方法:例如排序和查找
使用语句: import java.util.Arrays;
(1).对数组排序,可以对整个数组排序,也可以只对部分数组排序。如果电脑有多个处理器的话,使用parallelSort
效率会更高。
double[] numbers = {6.0, 4.4, 1.9, 2.9, 3.4, 3.5};
java.util.Arrays.sort(numbers); // Sort the whole array
java.util.Arrays.parallelSort(numbers); // Sort the whole array
char[] chars = {'a', 'A', '4', 'F', 'D', 'P'};
java.util.Arrays.sort(chars, 1, 3); // Sort part of the array: 1 ~ 3-1
java.util.Arrays.parallelSort(chars, 1, 3); // Sort part of the array
(2).使用二进制查找之前,数组必须先以递增的顺序排序过,如果失败则返回 –(insertionIndex + 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[] chars = {'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'));
(3).使用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
(4).使用fill
方法填充数组:
int[] list1 = {2, 4, 7, 10};
int[] list2 = {2, 4, 7, 7, 7, 10};
java.util.Arrays.fill(list1, 5); // Fill 5 to the whole array
java.util.Arrays.fill(list2, 1, 5, 8); // Fill 8 to a partial array: 1 ~ 5-1
(5).使用toString
方法返回数组所有元素的字符串表示:
int[] list = {2, 4, 7, 10};
System.out.println(Arrays.toString(list)); // 输出: [2, 4, 7, 10]
10. 命令行参数
main方法可从命令行接收字符串参数
main
方法可以像一般方法一样被调用, 下例中,class A
调用了class TestMain
中的main
函数:
// Part 1
public class TestMain {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++)
System.out.println(args[i]);
}
}
// Part 2
public class A {
public static void main(String[] args) {
String[] strings = {"New York", "Boston", "Atlanta"};
TestMain.main(strings);
}
}
可以从命令行传参数给main
方法,格式如:
java TestMain arg0 arg1 arg2
参数如果不是有空格,则不必加双引号:
java TestMain "First num" alpha 53
当main
方法被调用时,Java 解释器创建数组存储命令行参数,并将引用传给args
。
如果没有参数,args
非null
, 但 args.length
为 0.
书上还有计算器的实现例子,先省略。
[1] Introduction to Java Programming 10th. chapter 7.