Java教学 Lesson5

Arrays

public class ArraysTestDrive {
	
	public static void main(String[] args)
	{
		// []代表这是一个array,并且array中的所有元素都是相同的int型
		// 使用new代表这是一个实例化的过程。左右分开看,右边是一个array类型的对象,左边arr是一个reference。
		// [5]意味着数组的长度是5,并且不可改变。注意声明完成之后,所有的5个元素都被设为默认值0
		int[] arr = new int[5];
		
		// 通过索引器[] + 下标,访问每个数组元素。注意不要越界。
		System.out.println(arr[0] + ", " + arr[1] + ", " + arr[2] + ", " + arr[3] + ", " + arr[4]);
		
		
		// 初始化方式一:逐个赋值
		arr[0] = 2;
		arr[1] = 3;
		arr[2] = 5;
		arr[3] = 7;
		arr[4] = 11;		
		System.out.println(arr[0] + ", " + arr[1] + ", " + arr[2] + ", " + arr[3] + ", " + arr[4]);
		
		
		// 初始化方式二:初始化列表
		int[] arr2 = {2, 3, 5, 7, 11};		
		System.out.println(arr2[0] + ", " + arr2[1] + ", " + arr2[2] + ", " + arr2[3] + ", " + arr2[4]);
		
		
		// 获得数组的长度
		int arrLength = arr.length;
		System.out.println("The length of arr: " + arrLength);
		
		
		// 遍历方式一:for循环
		for(int i = 0; i < arr.length; i++)
		{
		    arr[i] = 6;
		}
		System.out.println(arr[0] + ", " + arr[1] + ", " + arr[2] + ", " + arr[3] + ", " + arr[4]);
		
		// 遍历方式二:for-each循环。 更简洁,但是不具备删除或替换元素的能力。
		for(int element : arr)
		{
		   element = 9;
		}
		System.out.println(arr[0] + ", " + arr[1] + ", " + arr[2] + ", " + arr[3] + ", " + arr[4]);
		
		
		// 数组的类型可以是class,意味着数组里的元素都是object。我们说在for-each中不能更改元素,但是对象可以调用更改器。
	    Person reno = new Person("DingLei", 181, 84.2);  
	    Person pudding = new Person("ChenKexuan", 161, 45);  
	    Person shelly = new Person("HuangYujia", 168, 49);  
	    
		Person[] personQueue = { reno, pudding, shelly };
		System.out.println(personQueue[0].getName() + ", " + personQueue[1].getName() + ", " + personQueue[2].getName());
		
		for(Person person : personQueue)
		{
		   // 调用更改器OK
		   person.setName("Nobody");
		   
		   // 替换元素仍然不可以
		   person = new Person("Somebody", 100, 100);
		}
		System.out.println(personQueue[0].getName() + ", " + personQueue[1].getName() + ", " + personQueue[2].getName());
		
				
		
		// 数组是一个对象,所以传递的是引用
		changeArray(arr);
		System.out.println(arr[0] + ", " + arr[1] + ", " + arr[2] + ", " + arr[3] + ", " + arr[4]);
		
		// 数组元素,有可能是基础类型,也有可能是引用类型。注意区别对待。
		changePrimitiveElement(arr[0]);
		System.out.println(arr[0] + ", " + arr[1] + ", " + arr[2] + ", " + arr[3] + ", " + arr[4]);
		
		changeReferenceElement(personQueue[0]);
		System.out.println(personQueue[0].getName() + ", " + personQueue[1].getName() + ", " + personQueue[2].getName());
		
		
		// 分析算法。在一个有序数组中插入一个数字,插入后使数组仍然是有序的。
		int[] arr3 = {2, 4, 6, 8, 10};
		
		// 插入到第一个位置,后面所有元素都要移动,是worst case。 
		int[] arr4 = insertByOrder(arr3, 1); 
		// 插入到最后一个位置,没有一个元素需要移动,是best case
		int[] arr6 = insertByOrder(arr3, 12); // 2,4,6,8,10,12
		// 插入到中间的位置,是average case
		int[] arr5 = insertByOrder(arr3, 5); // 2,4,5,6,8,10
		
		
		
		// -------------------------- 次元的分割线,以下是二维数组------------------------------
		
		
		// 二维Array声明
		// [][]代表这是一个二维Array,并且具有3行4列
		int[][] mat = new int[3][4];
		

		// 初始化方式一:用索引器
		// 先初始化第一行
		mat[0][0] = 2;
		mat[0][1] = 6;
		mat[0][2] = 8;
		mat[0][3] = 7;
		// 再初始化第二行
		mat[1][0] = 1;
		mat[1][1] = 5;
		mat[1][2] = 4;
		mat[1][3] = 0;
		// 再初始化第三行
		mat[2][0] = 9;
		mat[2][1] = 3;
		mat[2][2] = 2;
		mat[2][3] = 8;
		
		
		// 初始化方式二:用初始化列表,直观明了
		int[][] mat2 = {
						{2, 6, 8, 7},
						{1, 5, 4, 0},
						{9, 3, 2, 8},				
		              };
		
		
		
		// 我们也可以这样理解,二维Array是行的Array
		// mat有3个元素,可以这样想象,mat表示为 { mat[0], mat[1], mat[2] }
		int matLen = mat.length;
		System.out.println(matLen);
		
		// 其中,mat[0]又是一个标准的一维Array
		// mat[0]有4个元素, mat[0]表示为 {2, 6, 8, 7}
		int[] firstRow = mat[0];
		int firstRowLen = mat[0].length;
		System.out.println(firstRowLen);
		System.out.println(firstRow[0] + ", " + firstRow[1] + ", " + firstRow[2] + ", " + firstRow[3]);
		
		// 在二维Array中访问到元素的话,必须同时指定行下标和列下标
		System.out.println(mat[1][1]);
		
		
		// 遍历方式一:for循环,row-column模式
		// 外层循环,先遍历行。 mat.length代表有多少行
		for(int r=0; r < mat.length; r++){			
			// 内层循环,再遍历列。 mat[r]代表有多少列
		    for(int c=0; c< mat[r].length; c++){
		    	// 有了行下标和列下标,才能拿到元素
		        System.out.print(mat[r][c] + ", ");
		    }
		}
		System.out.println();
		
		
		// 遍历方式二:for-each循环,row-column模式
		// 外层循环,先遍历行。 注意mat的元素mat[0], mat[1], mat[2],每个元素都是数组,所以类型是int[]
		for(int[] row : mat){
			// 内层循环,再遍历列。对于每行,例如mat[0],它里面每个元素才是int
		    for(int element : row){
		        System.out.print(element + ", ");
		    }
		}
		System.out.println();
		
		
		// 遍历方式三:逐行扫描。要谨记mat的元素是mat[0], mat[1], mat[2],每个元素都是一个数组。
		for(int r=0; r < mat.length; r++){
			printArray(mat[r]);
		}
		System.out.println();
		
	}
	
	public static void printArray(int[] array)
	{
		for(int element : array)
		{
			System.out.print(element + ", ");
		}
	}
	
	public static void changeArray(int[] array)
	{
		for(int i = 0; i < array.length; i++)
		{
			array[i] += 3;
		}
	}
	
	public static void changePrimitiveElement(int element)
	{
		element += 3;
	}
	
	public static void changeReferenceElement(Person element)
	{
		element.setName("Anybody");
	}

	public static int[] insertByOrder(int[] array, int newElement)
	{
		// 因为要插入一个数字,所以重新建一个数组扩大1个长度,并将原来的元素都拷贝过来。
		// 注意newArray的最后一个元素没有做初始化,这里会设置默认值为0.
		int arrLen = array.length;
		int[] newArray = new int[arrLen + 1];
		for(int i = 0; i < arrLen; i++)
		{
			newArray[i] = array[i];
		}
		
		// 从第一个元素开始遍历,找到新元素应该插入的位置
		int newArrLen = newArray.length;
		int newPosition = 0;
		while(newPosition < newArrLen - 1 && newElement > newArray[newPosition])
		{
			newPosition++;
		}
		
		// 找到合适的位置后
		// 该位置之后的元素都要往后移动一格
		// 该位置要填入新元素
		// 该位置之前的元素不需要做任何处理
		for(int i = newArrLen - 1; i > newPosition; i--)
		{
			newArray[i] = newArray[i - 1];
		}
		newArray[newPosition] = newElement;
		

		// 遍历新数组,输出结果
		for(int element : newArray)
		{
			System.out.print(element + ", ");
		}
		System.out.println();
		
		return newArray;
	}
	
}

ArrayList

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ArrayListTestDrive {
	
	@SuppressWarnings("deprecation")
	public static void main(String[] args)
	{
		// 声明,引用类型是接口List,创建出来的对象是ArrayList。这是为了多态。
		// 声明时,不需要指定长度,因为ArrayList是动态调整的。
		List<Person> personQueue = new ArrayList<Person>();
		
		// add方法:往ArrayList中添加元素
	    Person reno = new Person("DingLei", 181, 84.2);  
	    Person pudding = new Person("ChenKexuan", 161, 45);  
	    Person shelly = new Person("HuangYujia", 168, 49);
	    
	    personQueue.add(reno);
	    personQueue.add(pudding);
	    personQueue.add(shelly);
	    
	    // get方法:访问其中某个元素,索引值的规则跟Array一样
	    Person firstPerson = personQueue.get(0);
	    Person secondPerson = personQueue.get(1);
	    Person thirdPerson = personQueue.get(2);
	    System.out.println(firstPerson.getName() + ", " + secondPerson.getName() + ", " + thirdPerson.getName());
	    
	    // size方法:返回ArrayList的长度
	    int listSize = personQueue.size();
	    System.out.println(listSize);
	    
	    // set方法:更改其中某个元素
	    Person maxG = new Person("Guhaowei", 170, 70);
	    personQueue.set(0, maxG);
	    System.out.println(personQueue.get(0).getName() + ", " + personQueue.get(1).getName() + ", " + personQueue.get(2).getName());

	    
	    // add方法重载:可以在任意位置添加元素。
	    // 对比一下Array是怎么添加元素的,是不是特别简单?
	    personQueue.add(0, reno);
	    System.out.println(personQueue.get(0).getName() + ", " + personQueue.get(1).getName() + ", " + personQueue.get(2).getName()+ ", " + personQueue.get(3).getName());
	    
	    // remove方法:删除任意位置的元素
	    personQueue.remove(1);
	    System.out.println(personQueue.get(0).getName() + ", " + personQueue.get(1).getName() + ", " + personQueue.get(2).getName());
	    
		// iterator方法:获得一个迭代器
	    Iterator<Person> personItr = personQueue.iterator();
	    
	    
	    // ----------------------------华丽的分割线,以下讨论Iterator -----------------------------------
	    
	    // Iterator属于标准包 java.util
	    // 它是一个迭代器,可以遍历ArrayList。通过hasNext和next搭配
	    while(personItr.hasNext())
	    {
	    	Person person = personItr.next();
	    	System.out.print(person.getName() + ", ");
	    }
	    System.out.println();
	    
	    // 它始终保持着当前的位置,现在已经遍历完了,当前位置在数组结尾
	    // 如果我想重新遍历,再次调用personItr.hasNext()是不行的,因为肯定会返回false
	    // 所以必须重新声明一次Iterator
	    personItr = personQueue.iterator();
	    
	    // 其实for-each的背后机制,就是靠Iterator来实现遍历的。不断判断hasNext并获得next
	    for(Person person : personQueue)
	    {
	    	System.out.print(person.getName() + ", ");	    	

		    // 但是for-each不允许删除元素,以下会报错
	    	// personQueue.remove(person);
	    }
	    System.out.println();
	    
	    
	    // 如果把for-each翻译为Iterator的方式完全没问题,并且同时也具备了删除元素的能力
	    while(personItr.hasNext())
	    {
	    	personItr.next();
	    	personItr.remove();
	    }
	    System.out.println(personQueue.size());
	    
	    
	    
	    // ----------------------------华丽的分割线,以下讨论装箱和拆箱 -----------------------------------
	    
	    // ArrayList必须存储对象,而不是基础类型(比如double和int)
	    // 所以不能声明为 ArrayList<int> 而是 ArrayList<Integer>
	    List<Integer> list = new ArrayList<Integer>();
	    
	    
	    // 回顾一下,int是基础类型,Integer是它对应的引用类型
	    // int声明出来的是一个基础数值
	    int intValue = 1;
	    // Integer声明出来的是一个引用对象
	    Integer intObject = new Integer(1);
	    
	    
	    // 把int转换为Integer的过程,就是装箱。形象的理解为把一个基础数值装到对象这个箱子里。我们也称Integer是Wrapper Class
	    Integer intObject2 = new Integer(intValue);
	    // 把Integer转换为int的过程,就是拆箱。形象的理解为把对象箱子里的基础数值取出来。
	    int intValue2 = intObject2.intValue();
	    
	    // 类比一下把大象装进冰箱里总共分三步
	    // ①把冰箱门打开       ②把大象装进去                  ③把冰箱门关上
	    // ①把对象创建出来    ②把基础数值装进去对象    ③把对象引用赋给变量
	    
	    
	    // 为什么要费劲的做装箱、拆箱这个事情呢?
	    // 装箱用途一:为了使用ArrayList,前面已经讲了,ArrayList必须存储对象。
	    list.add(new Integer(1));
	    list.add(new Integer(2));
	    list.add(new Integer(3));
	    
	    // 装箱用途二:为了配合Generic,所有出现<E>的地方,E必须用引用类型来指定。
	    // 当然,ArrayList就是一个Generic的应用,Java中还有更多使用Generic的class。
	    
	    // 装箱用途三:为了调用一些方法
	    Double doubleObj = new Double(1.12);
	    boolean b1 = doubleObj.equals(Double.NaN); // 相等判断	    
	    int cr = doubleObj.compareTo(Double.MAX_VALUE); // 比较大小
	    String str = doubleObj.toString(); // 转化为字符串
	    
	    // 自动装箱与自动拆箱
	    // 简化刚才的用途一,语法上允许直接填入基础数值。
	    // 但是请注意,并不是说ArrayList可以填入基础数值,而是说基础数值自动装箱为对象了,这个过程是自动做的,就是为了工程师方便。
	    list.add(1);
	    list.add(2);
	    list.add(3);
	    
	    // 同理,当调用get方法时,原本应该获取到Integer对象,但是你可以直接用int,因为这里也自动拆箱了。
	    Integer int1 = list.get(0);
	    int int2 = list.get(0);
	    
	    // 最后,请注意,装箱和拆箱是有性能损失的。每一次装箱都是平白无故做了装大象的三个步骤。
	    // 所以处理数值时,不要用ArrayList,而是用原生的Array。
	    
	}
}

String

public class StringTestDrive {

	public static void main(String[] args) {
		
		// String是一个对象,我们通常把String对象称为"字符串"
		// String的作用就是表示一句话,通常用来显示在界面上。在我们学习课程中,通常用来配合System.out.print输出结果。
		
		// 双引号是字符串的标志,当被双引号包括起来,我们就意识到这是一个字符串
		String s1 = "Hello World";
		System.out.println(s1);
		
		// 字符串可以不包含任何字符串,我们称为空字符串,但记住它仍然是字符串,而不是空引用null
		String s2 = "";
		System.out.println(s2);
		
		// 字符串可以包含转义字符,回想我们之前学的 \n, \", \\
		String s3 = "I must\n go home";
		System.out.println(s3);
		
		
		// 声明方式一:声明一个对象最典型的方式 - new
		String s4 = new String("abc");
		
		// 声明方式二:语法糖,可以像一个基础类型一样声明,这是最常用的方式
		String s5 = "abc";
		
		
		// 字符串连接一:使用+连接两个字符串
		String s6 = "Hello " + "World";
		System.out.println(s6);
		
		// 字符串连接二:连接字符串和任意对象。
		// 这里会自动调用对象的 toString方法,所以实际上还是两个字符串连接。
		Person reno = new Person("Reno", 181, 84.7);
		String s7 = "Hello " + reno;
		System.out.println(s7);
		
		// 字符串连接三:连接字符串和基础数值。
		// 这里会将基础数值装箱变为对象,然后自动调用toString方法,所以实际上还是两个字符串连接。
		int someInt = 12345;
		String s8 = "Hello " + someInt;
		System.out.println(s8);
		
		// 注意:做字符串连接的前提是至少有一个为字符串,另一个才会自动调用toString方法。
		// 如果两个变量中没有一个字符串,是没法连接的。
		
		
		// ------------------------ 华丽的分割线,以下讨论String的数组特性---------------------
		
		// 其实可以把String当做一个数组来看待,数组的元素是字符 - char类型
		String s9 = "ABCDEFG"; 
		char[] s10 = {'A','B','C','D','E','F','G'};
		
		// 所以数组的一些特性就可以帮助理解String的方法
		
		// length方法:返回String的长度,也就是字符的个数
		int strLen = s9.length();
		System.out.println(strLen);
		
		
		// indexOf方法:返回在String中的位置
		// A在第1个位置,所以索引值是0
		int strIndex = s9.indexOf("A"); 
		System.out.println(strIndex);
		
		// CDE从第3个位置,所以索引值是2
		int strIndex2 = s9.indexOf("CDE"); 
		System.out.println(strIndex2);
		
		// 虽然有FG,但是没有FGH,所以找不到位置,返回-1
		int strIndex3 = s9.indexOf("FGH"); 
		System.out.println(strIndex3);
		
		
		// subString方法:从String中截断一段subString
		// 重载一:从某个位置截到尾
		// 索引是3,表示从第4个位置开始截取,所以返回DEFG
		String subStr1 = s9.substring(3); 
		System.out.println(subStr1);		
		
		// 重载二:从某个位置开始,到某个位置结束。 注意第2个参数表示"第一个你不想要的字符"
		// 第7个位置不想要,也就是截取第4个位置~第6个位置,返回DEF 
		String subStr2 = s9.substring(3, 6); 
		System.out.println(subStr2);	
		
		
		// 比较两个字符串:从左到右,逐个字符比较。 
		// 返回负数、0、正数,这个数字本身并无意义,主要是用数字的正负性来排序。
		// null < 0 < 1 < ... < 9 < A < B < .... < Z < a < b < ....z
		
		// 第一个字符 W > H,所以"World" > "Hello",所以result1 > 0
		int result1 = "World".compareTo("Hello");
		System.out.println(result1);

		// 第一个字符相等,第二个字符 E < e,所以"HELLO" < "Hello",所以result1 < 0
		int result2 = "HELLO".compareTo("Hello");
		System.out.println(result2);		

		// 前四个字符Hell都相等,第五个字符 null < o,所以"Hell" > "Hello",所以 result1 < 0
		int result3 = "Hell".compareTo("Hello");
		System.out.println(result3);	
		
		
		// 相等性判断:应当和比较的规则保持一致。 其实比较=0就意味着相等,<0或者>0都意味着不相等。
		boolean bool1 = "HELLO".equals("Hello");
		System.out.println(bool1);		
		
		boolean bool2 = "Hello".equals("Hello");
		System.out.println(bool2);		
		
		
	}
}

把数组作为参数传入



把数组元素作为参数传入 - 元素是基本类型



把数组元素作为参数传入 - 元素是引用类型




往数组插入一个元素




Collection API继承层次图




Array vs. ArrayList



二维数组



装箱



String的不可变性


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值