参考教材:Java核心技术卷(第10版) Horstmann
P1 Java基础
第1章 Java程序设计概述
第2章 Java程序设计环境
# 下载安装jdk,设置环境变量,验证是否安装成功
java -version# 运行的java文件
# 打开终端窗口,进入java文件目录,执行下述代码
javac welocome.java
java welcome
第3章 Java的基本程序设计结构
3.1 一个简单的Java应用程序
// 在笔记中只能以Main类运行
public class Main {public static void main(String[] args){ System.out.println("we will not use hello world!"); }
}// 注意事项:
// 1 Java 区分大小写
// 2 关键字public称为访问修饰符(access modifier)
// 3 关键字class表明Java程序中的全部内容都包含在类中
// 4 关键字class后面紧跟类名,名字必须以字母开头
// 5 源代码的文件名必须与公共类的名字相同,并用.java作为扩展名
// 6 用大括号划分程序的各个部分(通常称为块)。Java中任何方法的代码都用"{" 开始,用"}"结束
// 7 使用了System.out对象并调用了它的println方法。注意,点号(•)用于调用方法// 8 标准的命名规范:
// 类名是以大写字母开头的名词。如果名字由多个单词组成,每个单词的第一个字母都应该大写
// 称为胳蛇命名法。以其自身为例,应该写成CamelCase)
3.2注释
// 单行://
// 多行:/* */// 这是一个单行注释/*
这是一个多行注释
*/
3.3数据类型
8种基本数据类型:4整,2浮,1字符,1布尔
4整( byte, short,int,long), 2浮(float,double),char,boolean
public class Main {public static void main(String[] args) {byte bdata = 127;short sdata = 128;int idata = 32768;//后需加Llong ldata = 2147483648L;//后需加Ffloat fdata = 3.40282347E+38F;double ddata = 1.79769313486231570E+308;// 本质上是等价,适用于需要表示非 ASCII 字符或者难以直接输入的字符的场景// char c = '\u0022';char c = '"';boolean bl = true;System.out.println("byte bdata: " + bdata);System.out.println("short sdata: " + sdata);System.out.println("int idata: " + idata);System.out.println("long ldata: " + ldata);System.out.println("float fdata: " + fdata);System.out.println("double ddata: " + ddata);System.out.println("char c: " + c);System.out.println("boolean bl: " + bl);}
}
转义序列
转义序列是一种在编程语言等环境中,用于表示那些难以直接输入或具有特殊含义字符的表示方法。通过特定的字符组合(以反斜杠 \
开头 )来代表特定的字符或操作
\"
(双引号):当需要在字符串中表示双引号字符时使用,因为双引号在编程语言中常用来界定字符串边界,直接写会造成语法错误,用\"
就能在字符串内表示双引号字符 。例如"She said, \"Hello!\""
。
3.4变量
// 规则:
// 每个变量都有一个类型(type)。在声明变量时,变量的类型位于变量名之前
// 每个声明以分号结束。由于声明是一条完整的Java语句,所以必须以分号结束
// 变量名必须是一个以字母开头并由字母或数字构成的序列
// 不能使用Java保留字作为变量名
// 变量名对大小写敏感
double salary;// 变量初始化
// 声明一个变量之后,必须用赋值语句对变量进行显式初始化,千万不要使用未初始化的变量。
// 对一个已经声明过的变量进行赋值,就需要将变量名放在等号(=) 左侧,相应取值的Java表达式放在等号的右侧
int vacationDays;
vacationDays=12;// 也可以将变量的声明和初始化放在同一行
int vacationDays = 12
// 常量
// 利用关键字final表示
// 关键字final表示这个变量只能被赋值一次。一旦被赋值之后,就不能够再更改了。
// 习惯上,常量名使用全大写
// constant,不是 Java 的关键字
3.5运算符
// 使用算术运算符+、-、*、/表示加、减、乘、除运算
// 操作数都是整数时,表示整数除法;否则,表示浮点除法// Math类
// 在Math类中,包含了各种各样的数学函数
// 要想计算一个数值的平方根,可以使用sqrt方法
double x = 4;
double y = Math.sqrt(x);// 在Java中,没有幂运算,因此需要借助于Math类的pow方法
double y = Math.pow(x, a);// 两个用于表示π和e常量的近似值
Math.PI
Math.E
数值类型之间的转换
数值类型之间的转换
将一种数值类型转换为另一种数值类型。
在图3-1中有6个实心箭头,表示无信息丢失的转换;有3个虚箭头,表示可能有精度损失的转换。
例如,123456789是一个大整数,它所包含的位数比float类型所能够表达的 位数多。当将这个整型数值转换为float类型时,将会得到同样大小的结果,但却失去了一定 的精度。
public class Main{public static void main(String[] args){int n = 123456789;float f = n; // f is 1.2345679E8System.out.println(n);System.out.println(f);}
}
强制类型转换
在必要的时候,int类型的值将会自动地转换为double类型。但另 一方面,有时也需要将double转换成int , 在Java中,允许进行这种数值之间的类型转换。 当然,有可能会丢失一些信息
在这种情况下,需要通过强制类型转换(cast) 实现这个操作。强制类型转换的语法格式是在圆括号中给出想要转换的目标类型,后面紧跟待转换的变量名
double x * 9.997;
int nx = (int) x;
// 在赋值中使用二元运算符,这是一种很方便的简写形式
X += 4;// 等价于:
x = x + 4;
// n++将变量n的当前值加1, n--则将n的值减1
int n = 12;
n++;// 上面介绍的是运算符放在操作数后面的“后缀” 形式。
// 还有一种“前缀” 形式:++n。后缀和前缀形式都会使变量值加1或减1。但用在表达式中时,
// 二者就有区别了。前缀形式会先完成加1; 而后缀形式会使用变量原来的值
int m = 7;
int n = 7;
int a = 2 * ++m; // now a is 16, m is 8
int b = 2 * n++; // now b is 14, n is 8
// 建议不要在表达式中使用++
// 要检测相等性,可以使用两个等号==
3 == 7
// 使用!=检测不相等
3 != 7
// 还有经常使用的<(小于)、> (大于)、<=(小于等于)和>=(大于等于)运算符
// 使用&&表示逻辑“ 与” 运算符,使用丨|表示逻辑“ 或” 运算符。
// 从!=运算符可以想到,感叹号!就是逻辑非运算符// &&和丨|运算符是按照“ 短路” 方式来求值的:
// 如果第一个操作数已经能够确定表达式的值,第二个操作数就不必计算了
x != 0 M 1/ x > x + y // no division by 0
// 处理整型类型时,可以直接对组成整型数值的各个位完成操作。
// 这意味着可以使用掩码技术得到整数中的各个位
// 位运算符包括
& ("and") | ("or") ^ ("xOr") ~ ("not")
// 这些运算符按位模式处理。// 例如,如果n是一个整数变量,而且用二进制表示的n从右边数第4位为1,则会返回1,否则返回0
int fourthBitFromRight = (n & 0b1000) / 0b1000;// 应用在布尔值上时,&和丨运算符也会得到一个布尔值。这些运算符与&&和丨丨运
// 算符很类似,不过&和丨运算符不采用“ 短路” 方式来求值// >>和<<运算符将位模式左移或右移。需要建立位模式来完成位掩码时,这两个运算符会很方便:
int fourthBitFromRight = (n & (1<<3))>>3;
括号与运算符级别
表3-4给出了运算符的优先级。如果不使用圆括号,就按照给出的运算符优先级次序进 行计算。同一个级别的运算符按照从左到右的次序进行计算(除了表中给出的右结合运算符外)
a || b && c
// 等价于
a || (b && c)// +=是右结合运算符
a += b += c
// 等价于
a += (b += c)
// 变量的取值只在一个有限的集合内。
// 例如:销售的服装或比萨饼只有小、中、大和超大这四种尺寸
// 针对这种情况,可以自定义枚举类型。枚举类型包括有限个命名的值
enum Size {SMALL, MEDIUM, LARGE, EXTRA_LARGE};
// 声明这种类型的变量
Size s = Size.MEDIUM;
3.6字符串
字符串
从概念上讲,Java字符串就是Unicode字符序列
例如, 串“ Java\u2122” 由5个 Unicode 字符 J、a、v、a 和™
Java没有内置的字符串类型,而是在标准Java类库中提供了 一个预定义类,很自然地叫做String
每个用双引号括起来的字符串都是String类的一个实 例:
String e = ""; // an empty string
String greeting = "Hello";
// String 类的 substring方法可以从一个较大的字符串提取出一个子串
String greeting = "Hello";
String s = greeting.substring(0, 3);
// 创建了一个由字符“ Hel” 组成的字符串,第二个参数是不想复制的第一个位置
// substring 的工作方式有一个优点:容易计算子串的长度。字符串s.substring(a, b)的长度为b-a。
// 例如,子串“ Hel” 的长度为3-0=3
// 与绝大多数的程序设计语言一样,Java语言允许使用+号连接(拼接)两个字符串
String expletive = "Expletive";
String PC13 = "deleted";
String message = expletive + PC13;// 当将一个字符串与一个非字符串的值进行拼接时,后者被转换成字符串
// (在第5章中可以看到,任何一个Java对象都可以转换成字符串)
int age = 13;
String rating = "PC" + age;// 这种特性通常用在输出语句中。例如:
System.out.println("The answer is " + answer);// 如果需要把多个字符串放在一起,用一个定界符分隔,可以使用静态join方法:
String all = String.join(" / ", "S", "M", "L", "XL");// all is the string "S / H / L / XL"
// String 类没有提供用于修改字符串的方法
// 如何修改这个字符串呢?
// 在Java中实现这项操作非常容易。首先提取需要的字符,然后再拼接上替换的字符串// 不可变字符串却有一个优点:编译器可以让字符串共享
// 如果复制一个字符串变量,原始字符串与复制的字符串共享相同的字符
// Java的设计者认为共享带来的高效率远远胜过于提取、拼接字符串所带来的低效率
// 可以使用equals方法检测两个字符串是否相等
s.equals(t)
// s与t可以是字符串变量,也可以是字符串字面量。例如,下列表达式是合法的:
"Hello".equals(greeting)
// 要想检测两个字符串是否相等,而不区分大小写,可以使用equalsIgnoreCase方法。
"Hello".equalsIgnoreCase("hel1o")// 一定不要使用==运算符检测两个字符串是否相等!这个运算符只能够确定两个字串是否放置在同一个位置上
空串""是长度为0的字符串,可以调用以下代码检查一个字符串是否为空:
if (str.length()== 0)
// 或
if (str.equals(""))// 空串是一个Java对象,有自己的串长度(0) 和内容(空)。不过,String变量还可以存
// 放一个特殊的值,名为null, 这表示目前没有任何对象与该变量关联 // 要检查一个字符串是否为null, 要使用以下条件
if (str == null)// 要检查一个字符串既不是null也不为空串
if (str != null && str.length() != 0)
// Java 字符串由char值序列组成。从3.3.3节“ char类型” 已经看到,char数据类型是一
// 个采用UTF-16编码表示Unicode码点的代码单元。大多数的常用Unicode字符使用一个代
// 码单元就可以表示,而辅助字符需要一对代码单元表示。// length 方法将返回采用UTF-16编码表示的给定字符串所需要的代码单元数量
String greeting = "Hello";
int n = greeting.length(); //is 5// 想得到实际的长度,即码点数量,可以调用:
int cpCount = greeting.codePointCount(0, greeting.length());// 调用s.charAt(n)将返回位置 n的代码单元,n介于0 ~ s.length()-l 之间
char first = greeting.charAtO); // first is 'H'
char last = greeting.charAt(4); // last is ’o’// 得到第i个码点
int index = greeting.offsetByCodePoints(0, i);
int cp = greeting.codePointAt(index);
String API
文档地址:
Overview
Java Platform SE 8
Java 中的String类包含了50多个方法。绝大多数都很有用,使用的频繁非常高
java.lang.string 1.0
构建字符串
// 如果需要用许多小段的字符串构建一个字符串,那么应该按照下列步骤进行。首先,构
// 建一个空的字符串构建器
StringBuilder builder = new StringBuilderO;// 当每次需要添加一部分内容时,就调用append方法
bui1der.append(ch); // appends a single character
bui1der.append(str); // appends a string// 在需要构建字符串时就凋用toString方法
String completedString = builder.toString();
在JDK5.0中引入StringBuilder 类。这个类的前身是StringBuffer, 其效率稍有些 低,但允许采用多线程的方式执行添加或删除字符的操作
java.lang.StringBuilder 5.0
- StringBuilder():构造一个空的字符串构建器。
- int length():返回构建器或缓冲器中的代码单元数量。
- StringBuilder append(String str):追加一个字符串并返回this。
- StringBuilder append(char c):追加一个代码单元并返回this。
- StringBuilder appendCodePoint(int cp):追加一个代码点,并将其转换为一个或两个代码单元并返回this。
- void setCharAt(int i,char c):将第i个代码单元设置为c。
- StringBuilder insert(int offset,String str):在offset位置插入一个字符串并返回this。
- StringBuilder insert(int offset,Char c):在offset位置插入一个代码单元并返回this。
- StringBuilder delete(int startIndex,int endIndex):删除偏移量从startIndex到-endIndex-1的代码单元并返回this。
- String toString():返回一个与构建器或缓冲器内容相同的字符串。
3.7输入与输出
// 打印输出到“ 标准输出流”(即控制台窗口),只要调用System.out.println 即可
// 读取“ 标准输人流” System.in,通过控制台进行输人,
// 首先需要构造一个Scanner对象,并与“ 标准输人流” System.in关联
Scanner in = new Scanner(System.in);// 使用Scanner类的各种方法实现输入操作
// nextLine方法将输入一行
System.out.print("What is your name? ");
String name = in.nextLine();// 读取一个单词(以空白符作为分隔符)
String firstName = in.next();// 读取一个整数,就调用nextlnt方法
System.out.print("How old are you? ");
int age = in.nextlnt();
import java.util.*;/**
询问用户姓名和年龄,然后打印一条如下格式的消息
Hello, Cay. Next year, you'll be 57Scanner 类定义在java.util 包中
当使用的类不是定义在基本java.lang包中时,一定要使用import 指示字将相应的包加载进来*/
public class Main
{public static void main(String[] args){Scanner in = new Scanner(System.in);// get first inputSystem.out.print("What is your name? ");String name = in.nextLine();// get second inputSystem.out.print("How old are you? ");int age = in.nextInt();// display output on consoleSystem.out.println("Hello, " + name + ". Next year, you'll be " + (age + 1));}
}
格式化输出
public class Main{public static void main(String[] args){// 正常输出double x = 10000.0 / 3.0;System.out.print(x); //3333.3333333333335 // 用8个字符的宽度和小数点后两个字符的精度打印xSystem.out.printf("%8.2f", x); //3333.33// 在printf中,可以使用多个参数String name="cay";int age=12;System.out.printf("Hello, %s. Next year, you'll be %d", name, age);// 每一个以%字符开始的格式说明符都用相应的参数替换。// 格式说明符尾部的转换符将指示被格式化的数值类型:// f表示浮点数,s表示字符串,d表示十进制整数}
}
// 对文件进行读取,就需要一个用File对象构造一个Scanner对象
// 如果文件名中包含反斜杠符号,就要记住在每个反斜杠之前再加一个额外的反斜杠:
// “ c:\\mydirectory\\myfile.txt”
Scanner in = new Scanner(Paths.get("niyflle.txt"), "UTF-8");// 在这里指定了UTF-8字符编码,读取一个文本文件时,要知道它的字符编码
// 如果省略字符编码,则会使用运行这个Java程序的机器的“ 默认编码”。这不是一个好主意,
// 如果在不同的机器上运行这个程序,可能会有不同的表现。// 要想写入文件,就需要构造一个PrintWriter对象,在构造器中,只需要提供文件名
PrintWriter out = new PrintlulriterC'myfile.txt", "UTF-8");
// 访问文件与使用System.in和System.out —样容易
// 如果用一个不存在的文件构造一个Scanner, 或者用一个不能被创建的文件名构造一个PrintWriter,
// 那么就会发生异常
文件输入与输出api
- java.util.Scanner 5.0
-
- Scanner(File f)
-
-
- 构造一个从给定文件读取数据的Scanner。
-
-
- Scanner(String data)
-
-
- 构造一个从给定字符串读取数据的Scanner。
-
- java.io.PrintWriter 1.1
-
- PrintWriter(String fileName)
-
-
- 构造一个将数据写入文件的PrintWriter。文件名由参数指定。
-
- java.nio.file.Paths 7
-
- static Path get(String pathname)
-
-
- 根据给定的路径名构造一个Path。
-
3.8控制流程
与任何程序设计语言一样,Java使用条件语句和循环结构确定控制流程
本节先讨论条件语句,然后讨论循环语句,最后介绍看似有些笨重的switch语句
// 块 (block,即复合语句)是指由一对大括号括起来的若干条简单的Java语句
// 块确定了变量的作用域。一个块可以嵌套在另一个块中// 示例
public static void main(String[] args){int n;{int k;} // k is only defined up to here}// 不能在嵌套的两个块中声明同名的变量
public static void main(String[] args){int n;{int k;int n; // Error can't redefine n in inner block} // k is only defined up to here}
条件语句
在Java中,条件语句的格式为 :
if (condition) statement
这里的条件必须用括号括起来
// Java常常希望在某个条件为真时执行多条语句。在这种情况下,应该使用块语句 (blockstatement)
if (yourSales >= target){performance = "Satisfactory";bonus = 100;}
在Java 中,更一般的条件语句格式如下所示
if (condition) statement1 else statement2
重复地交替出现if..elseif... 是一种很常见的情况
// if-else
if(yourSales >= target) {performance = "Satisfactory";bonus = 100 + 0.01 * (yourSales- target);
}
else {performance = "Unsatisfactory";bonus = 0;}// if-else if
if(yourSales >= 2 * target){performance = "Excellent";bonus = 1000;
}
else if(yourSales >= 1.5 * target){performance = "Fine";bonus = 500;
}
else if(yourSales >= target){performance = "Satisfactory";bonus = 100;
}
else{System.out.println("You're fired");
}
while循环
当条件为true时,while循环执行一条语句(也可以是一个语句块)。一般格式为
while (condition) statement
如果开始循环条件的值就为false, 则while循环体一次也不执行
示例1:计算需要多长时间才能够存储一定数量的退休金,假定每年存 人相同数量的金额,而且利率是固定的
while 循环语句首先检测循环条件。因此,循环体中的代码有可能不被执行t 如果希望 循环体至少执行一次,则应该将检测条件放在最后。使用do/while循环语句可以实现这种操 作方式。它的语法格式为:
do statement while (condition);
for循环
// for 循环语句是支持迭代的一种通用结构
// 利用每次迭代之后更新的计数器或类似的变量来控制迭代次数 for(int i = 1;i <= 10; i++)System.out.println(i);
for 语句的第1部分通常用于对计数器初始化;第2部分给出每次新一轮循环执行前要检 测的循环条件;第3部分指示如何更新计数器。
有一条不成文的 规则:for语句的3个部分应该对同一个计数器变量进行初始化、检测和更新。若不遵守这一 规则,编写的循环常常晦涩难懂
for (int i = 10; i > 0; i--)System.out.println("Counting down . . . " + i);System.out.println("B1astoff!");// 在循环中,检测两个浮点数是否相等需要格外小心。下面的for循环
for (double x = 0; x != 10; x += 0.1) . . .
// 可能永远不会结束。由于舍入的误差,最终可能得不到精确值。例如,在上面的
// 循环中,因为0.1无法精确地用二进制表示,所以,x将从9.99999999999998跳到
// 10.099 999 99999998。
switch语句
在处理多个选项时,使用if/else结构显得有些笨拙。Java有一个与C/C++完全一样的 switch 语句。
switch语句将从与选项值相匹配的case标签处开始执行直到遇到break语句,或者执行到 switch i吾句的结束处为止。如果没有相匹配的case标签,而有default子句,就执行这个子句
有可能触发多个case分支。如果在case分支语句的末尾没有break语句,那么就 会接着执行下一个case分支语句。
// break 用于退出循环语句
// ,Java还提供了一种带标签的 break语句,用于跳出多重嵌套的循环语句。
// 有时候,在嵌套很深的循环语句中会发生一些不可预料的事情。此时可能更加希望跳到嵌套
// 的所有循环语句之外。通过添加一些额外的条件判断实现各层循环的检测很不方便。
// 这里有一个示例说明了break语句的工作状态。请注意,标签必须放在希望跳出的最外
// 层循环之前,并且必须紧跟一个冒号。// continue语句。与break语句一样,它将中断正常的控制流程。continue
// 语句将控制转移到最内层循环的首部
3.9大数值
如果基本的整数和浮点数精度不能够满足需求,那么可以使用jaVa.math包中的两个 很有用的类:Biglnteger 和BigDecimaL 这两个类可以处理包含任意长度数字序列的数值。 Biglnteger 类实现了任意精度的整数运算,BigDecimal实现了任意精度的浮点数运算。
// 使用静态的valueOf方法可以将普通的数值转换为大数值:
Biglnteger a = Biglnteger.valueOf(100);
// 遗憾的是,不能使用人们熟悉的算术运算符(如:+和*) 处理大数值。而需要使用大数
// 值类中的add和multiply方法。
Biglnteger c = a.add(b); // c = a + b
Biglnteger d = c.multiply(b.add(Biglnteger.valueOf(2))); // d = c * (b + 2)
3.10数组
数组
数组是一种数据结构,用来存储同一类型值的集合。通过一个整型下标可以访问数组中 的每一个值
在声明数组变量时,需要指出数组类型(数据元素类型紧跟[]) 和数组变量的名字
// 声明整型数组a
int[] a;// 声明并初始化
int[] a = new int[100];// 可以使用下面两种形式声明数组
// int[] a;
// int a[];// 创建一个数字数组时,所有元素都初始化为0。boolean数组的元素会初始化为fals,对
// 象数组的元素则初始化为一个特殊值null, 这表示这些元素(还)未存放任何对象。// 一旦创建了数组,就不能再改变它的大小(尽管可以改变每一个数组元素)
// 如果经常需要在运行过程中扩展数组的大小,就应该使用另一种数据结构:数组列表(arraylist)
// Java 有一种功能很强的循环结构,可以用来依次处理数组中的每个元素(其他类型的元
// 素集合亦可)而不必为指定下标值而分心// 这种增强的for循环的语句格式为:
for (variable : collection) statement// 定义一个变量用于暂存集合中的每一个元素,并执行相应的语句
// collection 这一集合表达式必须是一个数组或者是一个实现了Iterable接口的类对象(例如
// ArrayList)
for (int element : a)System.out.println(element):// 传统的for循环
for (int i = 0; i < a.length; i++)System,out.println(a[i]);// 有个更加简单的方式打印数组中的所有值,即利用Arrays类的toString方法。调
// 用 Arrays.toString(a), 返回一个包含数组元素的字符串,这些元素被放置在括号内,并
// 用逗号分隔
// 如:"[2,3,5,7,11,13]"
// 创建数组对象并同时赋予初始值的简化书写形式
// 不需要调用new
int[] smallPrimes = { 2, 3, 5, 7, 11, 13 };// 初始化一个匿名的数组
new intD { 17, 19, 23, 29, 31, 37}// 使用这种语法形式可以在不创建新变量的情况下重新初始化一个数组
small Primes = new int[] { 17, 19, 23, 29, 31, 37 };
// 在Java中,允许将一个数组变量拷贝给另一个数组变量。这时,两个变量将引用同一个数组
int[] smallPrimes = { 2, 3, 5, 7, 11, 13 };
int[] luckyNumbers = smallPrimes;
1uckyNumbers[5] = 12; // now smallPrimes[5] is also 12// 如果希望将一个数组的所有值拷贝到一个新的数组中去,
// 就要使用Arrays类的copyOf方法:
int[] copiedLuckyNumbers = Arrays.copyOf(luckyNumbers, luckyNumbers.length);// 第2个参数是新数组的长度。这个方法通常用来增加数组的大小:
luckyNumbers = Arrays.copyOf(luckyNumbers, 2 * luckyNumbers.length);
// 如果数组元素是数值型,那么多余的元素将被赋值为0; 如果数组元素是布尔型,则将赋值
// 为false。相反,如果长度小于原始数组的长度,则只拷贝最前面的数据元素。
// 每一个Java应用程序都有一个带String arg[] 参数的main方法。
// 这个参数表明main方法将接收一个字符串数组,也就是命令行参数
数组排序
// 要想对数值型数组进行排序,可以使用Arrays类中的sort方法:
// 这个方法使用了优化的快速排序算法
int[] a = new int[10000];
Arrays.sort(a)
import java.util.*;/*** This program demonstrates array manipulation.* @version 1.20 2004-02-10* @author Cay Horstmann此程序会让用户输入两个数值,一是需要抽取的号码数量,二是可抽取的最大号码。接着,它会从 1 到最大号码的范围内随机抽取指定数量的号码,最后把这些抽取的号码排序并输出。*/
public class LotteryDrawing
{public static void main(String[] args){Scanner in = new Scanner(System.in);System.out.print("How many numbers do you need to draw? ");int k = in.nextInt();System.out.print("What is the highest number you can draw? ");int n = in.nextInt();// fill an array with numbers 1 2 3 . . . nint[] numbers = new int[n];for (int i = 0; i < numbers.length; i++)numbers[i] = i + 1;// draw k numbers and put them into a second arrayint[] result = new int[k];for (int i = 0; i < result.length; i++){// make a random index between 0 and n - 1int r = (int) (Math.random() * n);// pick the element at the random locationresult[i] = numbers[r];// move the last element into the random locationnumbers[r] = numbers[n - 1];n--;}// print the sorted arrayArrays.sort(result);System.out.println("Bet the following combination. It'll make you rich!");for (int r : result)System.out.println(r);}
}
多维数组
多维数组将使用多个下标访问数组元素,它适用于表示表格或更加复杂的排列形式。
示例:建立一个数值表,用来显示在不同利率下投资$10,000会增长多少,利息每年 兑现而且又被用于投资
// 声明一个二维数组
// 与一维数组一样,在调用new对多维数组进行初始化之前不能使用它
double[][] balances;// 初始化
balances = new double[NYEARS] [NRATES]:// 数组被初始化和,就可以利用两个方括号访问每个元素,例如,balances[i][j]
不规则数组
Java实际上没有多维数组,只有一维 数组。多维数组被解释为“ 数组的数组。”
在前面的示例中,balances数组实际上是一个包含10个元素的数组,而每个元素 又是一个由6个浮点数组成的数组
表达式balances[i]引用第 i 个子数组,也就是二维表的第i行。它本身也是一个数组, balances[i][j] 引用这个数组的第j 项
构造一个“ 不规则” 数组,即数组的每一行有不同的长度
示例中,创建一个数组,第i行第j列将存放“ 从i个数值中抽取j个数值” 产生的结果