JavaSE–数组
一、数组定义
变量空间是可以存放数据的,但是每一个变量空间只能存放一个数据。
1、数组的概念
数组是同一种类型数据的集合;即能够存放多个相同类型的数据的容器。
2、数组的定义方式
数组是存放多个数据的容器,Java中需要使用new
关键字来创建容器,在创建容器时也要明确容器的大小,即容器中存放数据个数。有以下格式:
元素类型[] 数组名 = new 元素类型[元素个数或数组长度];
int[] arr = new int[3];//通过new关键字创建了一个长度为3,元素类型是int的数组实体。
3、数组用途
数组可以存储多个数据,而且可以对数据进行编号,从0开始。操作元素完成可以通过编号(索引)完成。
int[] arr = new int[3];
arr[0] = 3; //给数组编号(角标)为0的空间中存放int类型的常量值3
System.out.println(arr[1]);//输出数组编号为1空间中的值。
二、数组内存详解
1、java内存的分配
java内存分配:栈、堆、寄存器、常量池、静态域。
栈内存:存储局部变量,只要在方法中定义的都是局部变量。一旦声明周期结束,变量就会结束。
堆内存:存储都是实体(对象),每一个实体都有一个首地址,就是在内存中存储的位置。堆内存的变量都有初始化。
方法体中引用变量和基本变量都在栈上,其他都在堆中。
局部变量的引用型:会把对象存在堆中,而把引用存在栈中。
2、数组内存分配
int[] arr = new int[3];// 定义数组arr 指向 new 开辟的新数组地址
arr = null;// 定义数组arr 指向 null
说明:
- 程序执行main方法时,遇见
new int[3]
会在堆内存中开辟新空间,并给其分配一个地址(假设 0x34) - 数组各个空间都有默认的 编号(
角标或索引
),将编号中对应的数据根据数据类型
完成初始化。 - 数组创建成功,将数组的地址赋值给arr,让arr指向堆中内存。
- 程序继续进行,将arr的指引赋值为null,即arr不再指向堆中数组实体。
- 这是堆中的数组会被标记成垃圾,等待
垃圾回收站回收GC
释放堆中资源。
public class Demo08 {
public static void main(String[] args) {
int[] arr = new int[4];// 1.定义数组 数组编号称为角标 从0开始的
// 2.数组赋值
arr[0] = 34;// 给第一个元素赋值
arr[1] = 18;// 给第二个元素赋值
arr[2] = 57;// 给第三个元素赋值
System.out.println("数组arr的第二个元素是:"+arr[1]);
System.out.println(arr);// 数组arr对应在堆中的地址信息。
System.out.println("数组arr的第二个元素是:"+arr[3]);
char chas[] = new char[3];
System.out.println("chas[0]"+chas[0]);// 0
System.out.println(chas[0]==0);// 0对应的字符
boolean flags[] = new boolean[2];
System.out.println("flags[0]"+flags[0]);// false
String strs[] = new String[4];
System.out.println("strs[0]"+strs[0]);// null
}
}
3、数组常见问题
3.1、数组角标越界异常
public class Demo10 {
public static void main(String[] args) {
int arr[] = new int[3];
System.out.println(arr[3]);
}
}
3.2、数组空指针异常
public class Demo10 {
public static void main(String[] args) {
int arr[] = new int[3];
//System.out.println(arr[3]);
arr = null;
System.out.println(arr[3]);
}
}
三、数组应用
1、数组另一种定义格式
元素类型 数组名[] = new 元素类型[]{元素1,元素2,....元素n};
元素类型 数组名[] = {元素1,元素2,....元素n};
2、遍历数组
从角标0开始,主键递增的方位角标对应的每一位元素。
public class Demo12 {
public static void main(String[] args) {
int nums[] = {12,5,87,14,26};// 角标:0 1 2 3 4
for (int i = 0;i<5;i++){
System.out.println(nums[i]);
}
// Arrays.toString 快速打印数组内容 会打印 []
System.out.println(Arrays.toString(nums));
}
}
但是如果数组的内容异常庞大,这时候就需要确定数组的大小
。
// 数组对象的length属性存储了数组长度的信息。
System.out.println("nums数组的大小为:"+nums.length);
nums = new int[]{12,5,87,14,26,77,59,31,7,60,233,1514};
int arr_length = nums.length;
for (int i =0;i<arr_length;i++){
System.out.println(nums[i]);
}
3、数组求和
需求:求数组中所有元素的和
思路:
- 需要定义个功能,用来求数组中所有元素的
和值
。 - 定义功能,必须搞清楚两个明确。
- 明确1:有返回结果,即所求的
和值
,和值类型int
。 - 明确2:有未知参数参与。需要求和的
数组
,数组需要调用者传递给此功能。
- 明确1:有返回结果,即所求的
步骤:
- 定义变量记录
和
。 - 通过循环对数组进行遍历。
public class Demo01 {
public static int getSum(int []nums){
int res = 0;// 求和结果
int length = nums.length;// 获取长度
for (int i =0;i<length;i++){
res += nums[i];
}
return res;
}
// 数据类型... 形式参数 可变长度参数 就是数组
public static int getSum1(int... nums){
int res = 0;// 求和结果
int length = nums.length;// 获取长度
for (int i =0;i<length;i++){
res += nums[i];
}
return res;
}
public static void main(String[] args) {
int nums[] = {23,17,40,20};
int sum = getSum(nums);
System.out.println("数组的求和结果:"+sum);
}
}
4、数组求最值
需求:获取多个整数中最大值。
思路:
- 数据多了为了便于操作,先存储起来。需要容器,用
数组
。 - 多个数据需要进行比较。每次都有***较大***的数,需要记录下来和***下一个***数比较。
- 将数组中的元素都比一遍。最后,就获取到
最大值
。
步骤:
- 接收欲求最大值的数组。
- 定义一个变量记录住较大的数。
- 对数组进行遍历。让元素和较大的值进行比较。如果元素大于较大的数,用变量记录该元素。
- 遍历完成后,变量中记录就是
最大值
。
public class Demo02 {
/**
* 求数组最大值
* @param nums
* @return
*/
public static int getMax(int nums[]){
int max = nums[0];// 默认最大值为第一个元素
for (int i = 1;i<nums.length;i++){// 遍历数组的每一位
if (max<nums[i]){// 判断当前为是否比max大
max = nums[i];// 用大值替换max值
}
}
return max;
}
public static int getMaxIndex(int nums[]){
int max = 0;// 默认最大值为第一个元素的角标
for (int i = 1;i<nums.length;i++){// 遍历数组的每一位
if (nums[max]<nums[i]){// 判断当前为是否比max大
max = i;// 用大值的角标替换max值的角标
}
}
return nums[max];
}
public static void main(String[] args) {
int nums[] = {7,23,44,16,32,99,34,13};
Arrays.sort(nums);
//int max = getMaxIndex(nums);
//System.out.println("最大值是:"+max);
System.out.println(Arrays.toString(nums));
System.out.println(nums[nums.length-1]);
}
}
四、数组练习
1、将数组转成字符串
- 需求:将数组中的
数字
编程字符串
输出。如[12,22,13,18,15]
拼接后"1222131815"
。 - 思路:简单的方式就是利用了字符串和任何数据相加都是相连接。
+
- 步骤:
- 明确1:结果是什么类型?
字符串
类型。 - 明确2:参数有什么?一个
int
类型的数组。 - 1、定义字符串变量存储以后拼接的结果。
- 2、遍历数组。将每一个数组的
元素
和字符串
相连接。 - 3、判断不是最后一个元素,后面连接
逗号
,是最后一个元素,后面不连接逗号。 - 4、将连接后的字符串返回。
- 明确1:结果是什么类型?
/**
* 数组和字符串
*/
public class Demo03 {
public static String getStr(int nums[]){
String str = "[";// 开头
for (int i =0 ;i<nums.length;i++){// 遍历每一位
if (i == nums.length-1){
str += nums[i];// 最后一位
}else{
str += nums[i]+", ";// 非最后一位,需要 ,和空格
}
}
str += "]";// 结尾
return str;
}
// 纯数字字符串转化为数组
public static int[] getArr(String str){
int str_length = str.length();// 获取字符串长度。
int arr[] = new int[str_length];// 数组长度和字符长度保持一致
for(int i = 0;i<str_length;i++){
char c = str.charAt(i);// 截取每一位
int num = Integer.parseInt(c+"");// 字符串类型转化为数字类型。
arr[i] = num;// 每一位赋值
}
return arr;
}
public static void main(String[] args) {
//int nums[] = {23,17,3,45,83};
//String str = getStr(nums);
//System.out.println(str);
//System.out.println(Arrays.toString(nums));
//字符串截取
//String str1 = "java OOP";
//System.out.println(str1.charAt(1));
String str = "65778723617";
int[] arr = getArr(str);
System.out.println(getStr(arr));
str = "65-778-7-23-61-7";
String[] split = str.split("-");
System.out.println(Arrays.toString(split));
}
}
2、数组反转
需求:将数组中的数据进行反转,如[12,22,13,18,15]
反转后[15,18,13,22,12]
。
思路:
-
需要定义数组反转的功能:
明确1:函数运算的结果?
void
类型或者int[]
。明确2:参与运行的参数?一个,
int[]
数组。 -
***数组反转***就是将数组中的值进行位置互换。
互换的条件是:
- 0角标和length-1角标位置上的值互换。
- 1角标和length-2角标位置上的值互换。
- 以此类推。
-
互换到什么时候停止呢?只要头角标
大于等于
了尾角标就停止。 -
怎么互换呢?互换就是交换两个空间中的值,可以使用第三方变量。
(三元置换)
步骤:
- 定义功能,接收数组。
- 遍历数组,每遍历一次交换数组两个位置的上的值,
start
代表头角标,end
代表尾角标 - 交换每次遍历的两个空间
[start,end]
中的数据。
class ArrayTest4
{
public static void main(String[] args)
{
int[] arr = {12,22,13,18,15};
printArray(arr); // 输出
reverseArray(arr); // 反转
printArray(arr);// 输出
}
//1、定义功能,接受数组
public static void reverseArray(int[] arr)
{
//2、遍历数组,每遍历一次交换数组两个位置的上的值,
// start代表头角标,end代表尾角标
for (int start = 0,end=arr.length-1;start<end ;start++,end-- )
{
//3、交换每次遍历的两个空间中的数据
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
}
}
//此功能为打印数组
public static void printArray(int[] arr)
{
for (int i=0;i<arr.length ;i++ )
{
if(i!=arr.length-1)
System.out.print(arr[i]+",");
else
System.out.println(arr[i]);
}
}
}
3、数组使用心得
数组容器的特点:1、固定长度 2、元素都有索引
什么时候使用容器:数据多了,必须先进行存储。然后进行操作。
什么时候使用数组:数据多,数据个数确定,而且数据与顺序有对应关系。在分析需求时确定:
- 需求中的数据是否有对应的有序编号?
- 需求中的数据是否需要有序的编号?如果有,就用数组存储。
4、查表法
需求1:根据用户输入的数据
,显示对应的星期
。
思路:
- 星期有多个,个数固定。
- 星期对应的
有序编号
。有序的编号就可以作为索引
。所以可以使用数组
这种结构进行存储。 - 定义一个功能。根据给定的数据获取对应的星期。
public static String getWeek(int num)
{
if(num>7 || num<1) return num+"没有对应的星期";
//throw new RuntimeExcpetion(num+"没有对应的星期");
//定义一个数组,存储固定的星期数。这个称之为一个存储了对应关系的表。
String[] weeks = {"","星期一","星期二","星期三","星期四","星期五","星期六","星期日"};
//其实就是根据制定的索引在查表。
return weeks[num];
}
什么是查表法:
查表法:数据之间存在对应关系。通过关系中一方查询另一方。当对应关系存在,但没有一方是有序编号时,使用另一个容器 map(集合框架时学习)。
需求2 : 十进制–>十六进制。
思路:在前面讲解时,使用的&15(0B1111)
运算每次可以取出十进制的最低四位数值,并将其打印在控制台上,遇到了两个问题,数据顺序反。同时还会有打印出多个0。
***分析数据顺序反的原因***是&15
运算要执行多次,每次都将运算结果直接打印在控制台,若将这些值直接存储在容器中,存完之后按照相反的顺序打印出来,那么看到的数据就是正确的。
/**
解决方式:
1、顺序反?每运算出一位,不要打印,先存储。需要容器。
2、去除零?需要转换的数据会不断的右移,如果右移后剩余的二进制都是0,也就是没有有效位,就不需要进行&运算了。也就是不需要在往数组中存储了。
*/
class ArrayTest6
{
public static void main(String[] args)
{
int num = 60;
String str_hex = toHex(num);
System.out.println(str_hex);
}
public static String toHex(int num)
{
//1,定义容器。存储的是字符,长度为8.一个整数最多8个16进制位。
char[] chs = new char[8];
//2,定义一个用于操作数组的索引。
int index = chs.length;
while(num!=0)
{
int temp = num & 15; // 和数字15的二进制进行'与'运算。确定对应的16进制每一位是否有值。
if(temp > 9)
chs[--index] = ((char)(temp-10+'A'));
else
chs[--index] = ((char)(temp+'0'));
num = num >>> 4;// 无符号右移
}
System.out.println("index="+index);
return "0x"+toString(chs,index);
}
//定义一个功能,将字符数组转成字符串。
public static String toString(char[] arr,int index)
{
String temp = "";
for(int x=index; x<arr.length; x++)
{
temp = temp + arr[x];
}
return temp;
}
}
需求3:十进制–>十六进制(查表法)
思路:十进制转成十六进制的每一位都是十六进制元素中的某一个。十六进制的元素有很多固定个数。而且还有对应的编号。所以可以使用查表法!
class ArrayTest7
{
public static void main(String[] args)
{
int num = 26;
String str_hex = toHex(num);
System.out.println("hex:"+str_hex);
}
// 转化
public static String toHex(int num)
{
//1,建立表。
char[] chs = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
//2,创建临时容器。
char[] arr = new char[8];
//3,创建操作临时容器的角标。
int index = arr.length;
//4,通过循环对num进行& >>等运算。
while(num!=0)
{
//5,对num进行&运算。
int temp = num & 15;
//6,根据&运算后的结果作为角标查表,获取对应的字符。并将字符存储到临时容器中。
arr[--index] = chs[temp];
//7,对num进行右移。
num = num >>> 4;
}
return "0x"+toString(arr,index);
}
//定义一个功能,将字符数组转成字符串。
public static String toString(char[] arr,int index)
{
String temp = "";
for(int x=index; x<arr.length; x++)
{
temp = temp + arr[x];
}
return temp;
}
}
五、数组排序
如何让数组中的值变的有序呢,比如从小到大,或者从大到小的排列。
1、选择排序
选择排序是排序中的一种。算法原则(从小到大排序)
:先用数组中第一个空间值和数组中剩余的其他空间值 依次做比较,在比较的过程有任何值比第一个空间值小
,就用第一个空间值
和当前这个空间值
换位置,直到所有值
和第一个空间值
全部比较完。第一个空间
中就放着最小值
。接着在使用数组第二个空间值
和数组中剩下空间中值做比较,比较方式和前一次相同。以此类推,比较完成。
规律:第一个空间
和剩余空间
比一圈,第二个空间
在和剩余空间
比一圈,以此类推,到倒数第二个空间值和最后一个空间值比完,整个数组有有序了。正好符合了***外循环循环一次,内循环执行一圈***。即外循环控制每次到底使用哪个空间值和剩余空间比较,内循环提供剩余空间。
图解 :
public static void selectSort(int[] arr)
{
for(int x=0 ;x<arr.length-1; x++) //提供比较的空间角标
{
for(int y=x+1; y<arr.length; y++) //提供剩余空间的角标
{
if(arr[x]>arr[y]) //判断当前外循环角标位置上的值和内循环角标位置上的值
{
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
}
}
}
2、冒泡排序
冒泡排序算法原理:这种算法和生活中常见的水中气泡的浮沉类似。
数组冒泡算法(从小到大):
- 数字
第一个
空间值和第二个
空间值比较,把较大的值存在第二个空间中,接着第二个空间值和第三个
空间值作比较,较大的值存在第三个空间中,以此类推直到倒数第二个空间和倒数第一个
空间比较,把较大值存放在最后一个空间中。 - 由于
最后一个
空间已经是最大值了,那么第二轮算法和第一轮一样,只是最后一次比较是倒数第三个空间和倒数第二个空间比较。把较大的值存在倒数第二个空间中。 - 以此类推。
/**
* 冒泡排序。
*/
public static void bubbleSort(int[] arr)
{
for(int x=0; x<arr.length-1; x++)// 决定了比较范围。
{
for(int y=0; y<arr.length-1-x; y++)// 从0开始比较到指定范围,范围逐渐缩小。
{
if(arr[y]>arr[y+1])// 两两比较 升序
{
int temp = arr[y];
arr[y] = arr[y+1];
arr[y+1] = temp;
}
}
}
}
六、数组查找
1、一般查找
从组中第一个空间
开始查找,每取出一个空间值和待查找的数值做比较若相等,就返回当前角标
;若数组遍历结束,没有找到相等的值,则返回-1
。
public static int searchKey(int[] arr,int key)
{
//遍历查找。
for(int x=0; x<arr.length; x++)
{
if(arr[x]==key) return x;// 找到就返回。
}
return -1;//-1,代表的是角标不存在的情况。
}
2、折半查找
折半查找,必须保证数组已经是有序的。
思路:
- 通过角标先获取中间角标上元素。
- 让该元素和要找的数据比较。
- 如果要找的数大了,缩小范围,要找的范围应该是
中间的角标+1
= = = > ===> ===>尾角标
; 如果要找的数小了,要找的范围头角标
= = = > ===> ===>中间角标-1
。 - 不断如此重复,就可以找到元素对应的角标。
public static int binarySearch(int[] arr,int key)
{
//1,定义三个变量,记录头角标,尾角标,中间角标。
int max,min,mid;
min = 0;// 中
max = arr.length-1;// 大
mid = (max+min)>>1;// 小 max+min /2
while(arr[mid]!= key)// 遍历
{
if(key>arr[mid])
min = mid + 1;
else if(key<arr[mid])
max = mid - 1;
//判断元素是否存在。
if(max<min)
return -1;
mid = (max+min)>>1;
}
return mid;
}
七、二维数组
二维数组,其实就是一个数组中又装了一个数组。
1、二维数组定义
int[][] arr = new int[3][2];
定义了名称为arr的二维数组, 二维数组
中有3个一维数组
,每一个一维数组
中有2个元素
, 一维数组的名称分别为arr[0], arr[1], arr[2]
。
arr[1][1] = 78;// 二维数组赋值
System.out.println(arr);// [[I@e6f7d2//二维数组实体
System.out.println(arr[0]);// [I@3e0ebb//一维数组实体。
System.out.println(arr[0][0]);// 0 一维数组中的元素。
2、二维数组图解
3、二维数组的其他定义格式:
int[][] arr = new int[3][];// 定义一维数组为null的二维数组。
二维数组中有3个一维数组,每个一维数组都是默认初始化值null。
arr[0] = new int[3];
arr[1] = new int[1];
arr[2] = new int[2];
// 统一赋值
可以对这个三个一维数组分别进行初始化。
int[][] arr = new int[][]{{3,8,2},{2,7},{9,0,1,6}};
定义一个名称为arr的二维数组,二维数组中的有三个一维数组,每一个一维数组中具体元素也都已初始化。
- 第一个一维数组 arr[0] = {3,8,2};
- 第二个一维数组 arr[1] = {2,7};
- 第三个一维数组 arr[2] = {9,0,1,6};
- 第n个一维数组的长度表示方式:arr[n-1].length;
八、二维数组应用
1、二维数组求和
class Array2Demo
{
public static void main(String[] args)
{
int[][] arr = {{3,8,2},{2,7},{9,0,1,6}};
int sum = getSum(arr);
System.out.println("sum="+sum);
}
// 求二位数组的和值
public static int getSum(int[][] arr)
{
int sum = 0;
for (int i=0;i<arr.length ;i++ )// 遍历二维数组每一个一维数组
{
for (int j=0;j<arr[i].length ;j++ )// 遍历一维数组的每一个元素
{
sum += arr[i][j];
}
}
return sum;
}
}
延伸学习
一、数学函数
Java在Math类中提供了许多实用方法,来计算常用的数学函数。
1、三角函数
sin、cos和tan的参数都是以弧度作为单位的角度。asin和atan的返回值是 -π/2 ~ π/2 的一个弧度值,acos的返回值在 0 ~ π 之间。1°
相当于 π/180 弧度,90°
相当于 π/2 弧度,30°
相当于 π/6 弧度。
public class MathDemo {
public static void main(String[] args) {
// 获取系统π值(180°)
double pie = Math.PI;
double degrees = Math.toDegrees(pie / 2);
System.out.println("度数是:" + degrees);// 90°
double radians = Math.toRadians(30);
System.out.println("弧度值是:" + radians);// π/6
// sin值
System.out.println(Math.sin(0));
System.out.println(Math.sin(Math.toRadians(270)));
System.out.println(Math.sin(pie / 6));
System.out.println(Math.sin(pie / 2));
// cos值
System.out.println(Math.cos(0));
System.out.println(Math.cos(pie / 6));
System.out.println(Math.cos(pie / 2));
// asin
System.out.println(Math.asin(0.5));// π/6
System.out.println(Math.acos(0.5));// π/3
System.out.println(Math.atan(1.0));// π/4
}
}
2、指数函数
public class MathDemo01 {
public static void main(String[] args) {
// 指数函数
double e = Math.E;
System.out.println("e = " + e);// 自然数e
System.out.println(Math.exp(1));// e的1次方
System.out.println(Math.log(e));// 以e为底,log值
System.out.println(Math.log10(10));// 以10为底,log值
System.out.println(Math.pow(2,3));// 2的3次方
System.out.println(Math.pow(3,2));// 3的2次方
System.out.println(Math.pow(4.5,2.5));// 4.5的2.5次方
System.out.println(Math.sqrt(4));// 2的平方根
System.out.println(Math.sqrt(10.5));// 10.5的平方根
}
}
3、取整方法
public class MathDemo02 {
public static void main(String[] args) {
// ceil取整
System.out.println(Math.ceil(2.1));
System.out.println(Math.ceil(2.0));
System.out.println(Math.ceil(-2.0));
System.out.println(Math.ceil(-2.1));
// floor取整
System.out.println(Math.floor(2.1));
System.out.println(Math.floor(2.0));
System.out.println(Math.floor(-2.0));
System.out.println(Math.floor(-2.1));
// rint取整
System.out.println(Math.rint(2.1));
System.out.println(Math.rint(-2.0));
System.out.println(Math.rint(-2.1));
System.out.println(Math.rint(2.5));
System.out.println(Math.rint(4.5));
System.out.println(Math.rint(-2.5));
// round取整
System.out.println(Math.round(2.6f));
System.out.println(Math.round(2.0));
System.out.println(Math.round(-2.0f));
System.out.println(Math.round(-2.6));
System.out.println(Math.round(-2.4));
}
}
4、min、 max、 abs方法
min
和 max
方法用于返回两个数*(int、long、float和double型)*的最小值和最大值。例如:max(4.4,5.0
)返回5.0。而min(3,2)
返回2 。
abs方法
返回返回一个数*(int、long、float和double型)*的绝对值
。
public class MathDemo03 {
public static void main(String[] args) {
// max、min、abs
System.out.println(Math.max(2,3));
System.out.println(Math.max(2.5,3));
System.out.println(Math.min(2.5,4.6));
System.out.println(Math.abs(-2));
System.out.println(Math.abs(-2.1));
}
}
5、random方法
0.0 <= Math.random < 1.0
: 范围在 0.0
和 1.0
之间,取不到 1.0
。
6、计算三角形角度
根据一个三角形的三个边,计算构成三个角的角度。
public class ComputerAngles {
public static void main(String[] args) {
// 引入Scanner类,获取输入信息。
Scanner sc = new Scanner(System.in);
// 获取坐标
System.out.println("输入三个点坐标");
double x1 = sc.nextDouble();
double y1 = sc.nextDouble();
double x2 = sc.nextDouble();
double y2 = sc.nextDouble();
double x3 = sc.nextDouble();
double y3 = sc.nextDouble();
// 计算三条边 两点之间距离公式
double a = Math.sqrt((x2 - x3) * (x2 - x3) + (y2 - y3) * (y2 - y3));
double b = Math.sqrt((x1 - x3) * (x1 - x3) + (y1 - y3) * (y1 - y3));
double c = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
// 计算三角度数
double A = Math.toDegrees(Math.acos((a * a - b * b - c * c) / (-2 * b * c)));
double B = Math.toDegrees(Math.acos((b * b - a * a - c * c) / (-2 * a * c)));
double C = Math.toDegrees(Math.acos((c * c - b * b - a * a) / (-2 * a * b)));
// 输出
System.out.println("三个角分别是:" + Math.round(A * 100) / 100.0 + " " +
Math.round(B * 100) / 100.0 + " " +
Math.round(C * 100) / 100.0);
}
}
二、字符以及操作
1、字符
字符数据类型表示单个字符。
char letter = 'A';// 将 字符A 赋值给char类型的letter
char numChar = '4';// 将 数字字符A 赋值给char类型的numChar
注意:字符串直接量必须包括在双引号【""】
中,而字符直接量是括在单引号【''】
中的单个字符。因此"A"
是一个字符串,而'A'
是一个字符。
2、Unicode 和 ASCII 码
计算机内部使用二进制数。一个字符在计算机中以 0 和 **1 ** 构成的序列的形式来存储的。将字符映射到它的二进制形式的过程称为 编码(encoding)。字符有多种不同的编码方式,编码表(encoding scheme)定义该如何编码每个字符。
Unicode 一开始被设定为16位
的字符编码。基本数据类型 char
试图提供一种能存放任意字符的简单数据类型来利用这个设计。但是16位不足就扩展为 1 112 064***个字符。称之为***补充字符 (supplementary character)。
大多数计算机采用ASCII编码(美国标准信息交换码),它是所有大小字母、数字、标点符号和控制字符的 8
位编码表。Unicode 包含 ASCII 码。
char letter = 'A';
char letter = '\u0041';
//都是将字符A赋值给letter
注意:自增 和 自减操作符也可以运用在 char 类型变量上,得到当前字符之前和之后的 Unicode 字符。
char ch = 'a';
System.out.println(++ch);
3、特殊字符的转义序列
补充多个转义字符。
反斜杠 \
被称为转义字符。它是一个特殊字符。要显示这个字符,需要转义序列 \\
。
4、字符和数字转化
char类型数据可以转化成任意一种数值类型,反之亦然。将整个整数转化成 char 型数据时,只用到该数据的低十六位。其余部分忽略。
char ch = (char)0xAB0041;// 低16位的0041存储
System.out.println(ch);// 把A存储
要将一个 浮点值 转换成 char
型时,首先将 浮点值 转换成 int
型,然后将整个整型值
转换成 char
型。
char ch = (char)65.25;// 其实就是把65存储进入
System.out.println(ch);// 把A存储
当一个char
型数据转换成数值型时,这个字符的Unicode
码就被转换成某个特定的数值类型。
int i = (int)'A';// A的Unicode存储到i中。
System.out.println(i);// 把A存储
如果转换结果适用于目标变量,就使用隐式变量
;否则,必须使用强制类型转换方式。a的ASCII
十进制码是97在一个字节范围内。Unicode码 \uFFF4
超过一个字节。
byte b = 'a';
int i = 'a';
byte b = (byte)'\uFFF4';
0 ~ FFFF 的任何一个十六进制正整数都可以隐式地转成字符型数据。而超过此范围的都需要强制类型转化为char型。
5、比较和字符方法
两个字符可以使用关系操作符进行比较,就如同比较两个数字一样。这是通过比较两个字符的Unicode 值实现的。
char ch = 'A';// 任意
if(ch >='A' && ch <='Z') System.out.println("大写字母");
else if(ch >='a' && ch <='z') System.out.println("小写字母");
else if(ch >='0' && ch <='9') System.out.println("数字");
字符char有自己的封装类型Character,封装了很多方法以便我们使用。
public class CharDemo01 {
public static void main(String[] args) {
// 是否是数字
boolean isNumber = Character.isDigit('a');
// 是否是字母
boolean isCode = Character.isLetter('a');
// 是否是字母或数字
boolean letterOrDigit = Character.isLetterOrDigit('a');
// 是否是小写字符
boolean lowerCase = Character.isLowerCase('a');
// 是否是大写字符
boolean upperCase = Character.isUpperCase('a');
// 转小写
char lowerCase1 = Character.toLowerCase('a');
// 转大写
char upperCase1 = Character.toUpperCase('a');
}
}
三、String类型
String 字符串其实就是一个字符序列。
1、获取长度
调用 length()
方法获取长度。具体代码如下:
String message = "This is a long String.";
System.out.println(message.length());// 获取字符串长度
使用一个字符串的时候,往往知道它的字面值常量的。为了方便,Java允许再不创建新的字符串的情况下,使用字符串直接使用字面值常量。所以,“This is a long String.”.length() 是正确的。而且 “”.length() 的值为0,""不是null。
2、截取字符
方法 s.charAt(index)
可用于提取字符串s中某个指定的字符,其下标取值在[0 ,s.length() - 1]。
警告:如果访问的长度超过了s.length() - 1
,就会造成一种常见的程序设计错误,访问越界错误,发生:StringIndexOutOfBoundsException()
异常。
3、字符串转化
方法toLowerCase()
返回一个新字符串,其中所有字母都小写;方法toUpperCase()
返回一个新字符串,其中所有字母都大写。
"WelCome".toLowerCase();// welcome
"WelCome".toUpperCase();// WELCOME
方法 trim 通过删除字符串两端的空白字符返回一个新字符串。字符 ’ ’ 、\t、\f、\r、\n都被称为空白字符:
"\t Good Night \n".trim();// "Good Night"
4、字符串比较
除了之前的 equals()
方法以外,还可以使用 compareTo()
方法来比较两个字符串。
s1.compareTo(s2);// 如果 s1 和 s2 相等,那么返回0。如果按照字典顺序(Unicode码顺序)s1 < s2 ,那么该方法返回值小于0;如果s1 > s2 ,那么该方法返回值大于0。
实际上比较每一位字符之间的距离和。
5、获取子字符串
方法 s.charAt(index)
可用于提取字符串s中某个指定的字符,也可以使用 substring 获取一个字符串。
String message = "Welcome to Java";
String message = message.substring(0,11) + "HTML";
// "Welcome to Java" 变成了 "Welcome to HTML"
6、字符串和数字转化
可以将数值型字符串转化为数字,要将字符串转化为int,使用Integer的parseInt方法;
int intValue = Integer.parseInt(intString);// intString 数值型字符串,例如"123"。
其它数值就采取同样的方法来转化,如:Double.parseDouble(doubleString)
转化一个 数值型字符串 如:“4.13”。
而数字转化为字符串,只需要简单的字符串的连接符就行;
String s = number + "";
四、格式化输出
System.out.printf(format,item1,item2.....item n);
format:一个字符串和字符串格式标识符构成的字符串。
格式标识符 指定每个条目应该如何显示。这里条目就是数值、字符、布尔值或字符串。简单的格式标识符是以(%)开头的转换码。
条目与格式标识符必须在类型上严格匹配。对应于格式标识符 %f 或 %e 的条目必须是浮点型。
使用符号%来标记格式标识符,要在格式字符串里输出直接量%,需要使用%%。
默认情况下输出右对齐,可以在格式标识符中放一个负号(-),表示输出是左对齐。
public class FormatDemo01 {
public static void main(String[] args) {
System.out.printf("%-10s%-10s%-10s%-10s%-10s\n","Degrees","Radians","Sine"
,"Cosine","Tangent");
int degrees = 30;
double radians = Math.toRadians(degrees);
System.out.printf("%-10d%-10.4f%-10.4f%-10.4f%-10.4f\n",degrees,radians,
Math.sin(radians),Math.cos(radians),Math.tan(radians));
degrees = 60;
radians = Math.toRadians(degrees);
System.out.printf("%-10d%-10.4f%-10.4f%-10.4f%-10.4f\n",degrees,radians,
Math.sin(radians),Math.cos(radians),Math.tan(radians));
}
}