其实编写程序就是把数据拿在手中玩儿,对不?

 

Java用来干嘛?

编写程序!程序又拿来干嘛?处理现实中的问题?什么问题?一系列复杂的逻辑,运算等!

其实,程序的功能就是为现实生活中遇到的问题进行服务。

为企业进行服务,处理数据,一切都是以数据为中心开展的活动!

数据才是核心!!!

既然数据如此重要,程序中如何处理各种数据呢?-------使用容器

处理数据时使用容器能够有效的对数据进行管理,非常方便!

 

必须滚瓜烂熟的掌握容器!!!

Java中用来存放数据的容器,各自有自身的特性,适用于不同的场景!

 

第一种:数组   

一维数组  

二维数组

 

第二种:集合   

List集合   

Set集合 

Map集合

 

=============================================================

 

数组的常见操作

求最值

public class Test {
	
	/**
	 * 求数组中的最大值
	 * @param args
	 */
	public static void main(String[] args) {
		//静态初始化一个int类型的数组,
		int[] arr = {-1,5,-2,8,3,0};
		
		int maxElement = getMax(arr);
		
		System.out.println("maxElement="+maxElement);
		
		System.out.println("maxElement="+getMax2(arr));
	}
	
	/**
	 * 第一种思路:每次记录最大的数
	 * @param arr
	 * @return
	 */
	public static int getMax(int[] arr) {
		//数组的第一个元素
		int maxElement = arr[0];
		for(int i=1; i<arr.length; i++) {
			if(arr[i] > maxElement)
				maxElement = arr[i];
		}
		return maxElement;
	}
	
	/**
	 * 第二种思路:每次记录最大数在数组中的角标位
	 * @param arr
	 * @return
	 */
	public static int getMax2(int[] arr) {
		//数组的第一个角标
		int maxElementIndex = 0;
		for(int i=1; i<arr.length; i++) {
			if(arr[i] > arr[maxElementIndex]) {
				maxElementIndex = i;
			}
		}
		return arr[maxElementIndex];	
	}
}

 

数组的排序

【这里只是演示排序的思想,实际开发中不要用选择与冒泡进行排序,因为效率太低】

选择排序

原理:每次都以某个角标位为基准与后面的所有数进行比较。

 

实际上就是以角标为中心,每次把该角标上的数与后面的所有数进行比较。

 

选择排序,其特点是完全按照线性顺序逐个比较元素的,啃着1个位置与其它元素比较

 

如,0号位元素,先与1号位元素比,发现1号位的元素更小,它们交互位置

交互位置后,0号位元素存放的是小值,

然后,再拿0号位这个'最小值'与2号位比较。。。

import java.util.Arrays;


public class SelectSort {
	public static void main(String[] args) {
		int[] arr = new int[]{100,3,1,39,6,7,2};
		sort(arr);
		System.out.println(Arrays.toString(arr));
	}
	
	/**
	 * 以升序为例
	 * 第1次:数组的0角标位始终用来存放最小值(每次比较如果有比它小的,则交换位置,将小的数放到0角标,然后再逐个与后面的数比较)
	 * 第2次,数组的1号角标位又用来存放后面这些数中最小的那个值
	 * 依次类推
	 * 当角标位等于数组长度减2时,进行最后一次比较,即数组最后2个数之间比较
	 * @param arr
	 */
	private static void sort(int[] arr) {
		//外层:锁定每次排序用来存储最值的角标
		//当i=arr.length-1的时候,实际已经为数组的最后一个元素了,一个数无需再比较了
		for (int i = 0; i < arr.length-1; i++) {
			//内层:逐个比较,得到一个最值(最后1次比较时,j=arr.length-1)		
	        for (int j = i+1; j < arr.length; j++) {
				//后面的数更小,则交互位置
				if(arr[j] < arr[i]) {
					arr[j] = arr[j] ^ arr[i];
					arr[i] = arr[j] ^ arr[i];
					arr[j] = arr[j] ^ arr[i];
				}
			}
		}
	}
}


 

优化选择排序

 优化结果:减少数据交换位置的动作,每次遍历后都只对锁定角标位上的值与最值进行交换

import java.util.Arrays;


public class SelectSortImprove {
	public static void main(String[] args) {
		int[] arr = new int[]{10,3,9,-1,8,7,6,5,4,3,2,1};
		sort(arr);
		System.out.println(Arrays.toString(arr));
	}
	
	/**
	 * 选择排序的改进
	 * 改进的地方:
	 * 每次比较出最小值,不立刻交换位置
	 * 而是记录最小值的角标,再拿这个角标的值与其它元素进行比较
	 * 一次遍历,得到最小值的角标,再与数组中锁定的角标位进行值的交换动作
	 * @param arr
	 */
	public static void sort(int[] arr) {
		for (int i = 0; i < arr.length-1; i++) {
			int minElementIndex = i;
			for (int j = i+1; j < arr.length; j++) {
				if(arr[minElementIndex]>arr[j]) {
					minElementIndex = j;
				}
			}
			if(i != minElementIndex)
				swap(arr,i,minElementIndex);
		}
	}

	private static void swap(int[] arr, int i, int minElementIndex) {
		arr[i] = arr[i] ^ arr[minElementIndex];
		arr[minElementIndex] = arr[i] ^ arr[minElementIndex];
		arr[i] = arr[i] ^ arr[minElementIndex];
	}
}

 

 

 

 

冒泡排序

import java.util.Arrays;


public class BubbleSort {
	public static void main(String[] args) {
		int[] arr = new int[]{10,9,8,7,6,5,4,3,2,1};
		sort(arr);
		System.out.println(Arrays.toString(arr));
	}
	/**
	 * 冒泡排序
	 * 特点:相邻元素逐个比较
	 * 一次遍历之后,大数都尽量往后靠了,并且最大的数放到了最后
	 * @param arr
	 * @return
	 */
	private static void sort(int[] arr) {
		//外层:决定内层循环的次数
		for (int i = 0; i < arr.length-1; i++) {
			//内层:比较相邻的元素
			//-1 是为了防止角标越界
			//-i是参与比较的元素递减
			for (int j = 0; j < arr.length-i-1; j++) {
                        //升序
				if(arr[j]>arr[j+1]) {
					arr[j] = arr[j] ^ arr[j+1];
					arr[j+1] = arr[j] ^ arr[j+1];
					arr[j] = arr[j] ^ arr[j+1];
				}
			}
		}
	}
}

 

 开发中这样排序

public static void main(String[] args) {
	//数组中元素的排序
	int[] arr = new int[]{10,9,8,7,6,5,4,3,2,1};
	//Arrays类提供了针对数组操作的方法
	Arrays.sort(arr);
	System.out.println(Arrays.toString(arr));
	
	//集合中元素的排序
	List<BigDecimal> list = new ArrayList<BigDecimal>();
	list.add(new BigDecimal(100.1));
	list.add(new BigDecimal(20));
	list.add(new BigDecimal(88.8));
	//Collections类提供了对集合的排序(集合中的元素如果没有实现Comparable接口,则需要手动指定一个比较器)
	//BigDecimal extends Number implements Comparable<BigDecimal>
	Collections.sort(list);
	for(BigDecimal b : list) {
		System.out.println(b.doubleValue());
	}
}

 

数组中的查找

无序数组中查找元素

public class ArraySearch {
	/**
	 * 无序数组的查找
	 * @param args
	 */
	public static void main(String[] args) {
		int[] arr = {1,5,2,7,4,0};
		int key = 5;
		int index = searchElement(arr,key);
		System.out.println(key+"在数组arr中的角标位:"+index);
	}

	private static int searchElement(int[] arr, int key) {
		for(int i=0; i<arr.length; i++) {
			//无序数组的查找,只能挨个比较
			if(arr[i] == key)
				return i;
		}
		return -1;
	}
	
	
}

  

 有序数组的查找

基于有序的特点,可以提高查找效率

 由于数组有序,以升序为例,不用挨个比较,可以跳跃着比较,因为数组已经有序

【不要为了使用二分查找而对一个数组进行排序!这样已经没意义了,因为数组都变了!~】

被操作的数组前提是有序的(升序/降序),在此基础上才能使用二分查找法!

 

public class ArraySearch {
	/**
	 * 有序数组的查找
	 * @param args
	 */
	public static void main(String[] args) {
		int[] arr = {1,3,5,7,9};
		int key = 5;
		int index = binarySearch(arr,key);
		System.out.println(key+"在数组arr中的角标位:"+index);
	}

	private static int binarySearch(int[] arr, int key) {
		
		int min = 0, max = arr.length-1, mid = (min+max)>>1;
		
		//循环结束的条件:min 大于 max,再比较已经没有意义,循环结束
		while(min <= max) {
			if(arr[mid] < key) {
				//中间数  < key,移动min角标,指向mid的后一位
				min = mid + 1;
			} else if(arr[mid] > key) {
				// 中间数 > key,移动max角标,指向mid的前一位
				max = mid - 1;
			} else {
				return mid;
			}
			//如果没有找到,从新定位mid的位置
			mid = (min+max)>>1;
		}
		
		return -1;
	}
	
	
}

 

 

开发中对有序数组这样查找

import java.util.Arrays;


public class ArraySearch {
	/**
	 * 使用Arrays类中的binarySearch方法对有序数组进行查找
	 * @param args
	 */
	public static void main(String[] args) {
		int[] arr = {1,3,5,7,9};
		int key = 2;
		//binarySearch()对数组进行查找,底层做了2个操作
		//1.如果查找到,则返回元素的角标
		//2.如果没有找到,则告诉你该元素应该插入到数组的哪个位置(插入后数组仍有序):
		//  index: -(insertion point) -1 ,既保证不存在时返回负数,又能明确了插入位置
		int index = Arrays.binarySearch(arr, key);
		System.out.println(key+"在数组arr中的角标位:"+index);
		//返回-2
		//表示数组中没有2这个元素,而且如果要插入到数组中,其角标位是 |(-2 + 1)| = 1
	}
}

 

 数组的应用---进制转换---把数组当做一张表来使用

/**
 * 数组的灵活运用
 * 查表法
 * 一组数与另一组数有对应关系,则用数组来操作,用一个数组定义一个对应关系表
 * 如果有对应关系,但是不连续,则用Map
 * 其实这里的数组是一个特殊的Map,其key就是数组的角标
 * 而这个key就是程序中运算的结果,这样,直接从数组中取即可!
 * @param args
 */
public class ArrayUse {
	/**
	使用数组定义一张映射关系表---10进制数与16进制的对应关系
	玄机:转换为得到的10进制数与对应的16进制字符在表中的角标相同
	*/
	static 	char[] hexTable = {'0','1','2','3','4',
							   '5','6','7','8','9',
							   'A','B','C','D','E'};
	
	public static void main(String[] args) {
		int num = 0;
		char[] retHex = toHex(num);
		for(char c : retHex) {
			 if( Character.isDigit(c) || Character.isLetter(c) )
				 System.out.print(c);
		}
	}
	
	public static char[] toHex(int num) {
		//32位系统上,最多就是8个16进制 (32/4=8)
		int len = 8;
		//从数组的最后一位开始存,后面就不需要反转数组了
		int pos = len -1;
		//定义一个用来存放转换后结果的数组
		char[] hexResult = new char[len];
		
		//do... whlie()保证至少执行一次,这样保证num==0的情况下也有结果
		do{
			// 15 的 2进制 : 1111,将最后4位与1111进行与
			int temp = num & 15;
			//使用temp作为角标到表中查找对应的16进制字符
			hexResult[pos--] = hexTable[temp];
			// 取下一组4个比特位的数
			num = num >>> 4;
		} while(num != 0);
		
		return hexResult;
	}
}

 

 10进制与其它进制的转换(整合)

 

public class ArrayUse {
	/**
	使用数组定义一张映射关系表---10进制数与16进制的对应关系
	玄机:转换为得到的10进制数与对应的16进制字符在表中的角标相同
	*/
	static 	char[] baseTable = {'0','1','2','3','4',
							   '5','6','7','8','9',
							   'A','B','C','D','E'};
	/**
	使用枚举存储进制类型
	各进制中有一个属性:10进制转换为该进制每次移动的位数
	*/
	static enum Base {
		binary(1),octal(3),hex(4);
		private int offset;
		private Base(int offset) {
			this.offset = offset;
		}
	}
	
	public static void main(String[] args) {
		int num = 60;
		int base = 2;
		char[] convert = numberConvert(num, base);
		for(char c : convert) {
			 if( Character.isDigit(c) || Character.isLetter(c) )
				 System.out.print(c);
		}
	}
	
	/**
	 * 
	 * @param num  需要进制转换的数
	 * @param base 进制
	 * @param offset  每次左移的位数
	 * @return
	 */
	public static char[] numberConvert(int num, int base) {
		//32位系统
		int len = 32;
		//从数组的最后一位开始存,后面就不需要反转数组了
		int pos = len -1;
		//定义一个用来存放转换后结果的数组
		char[] hexResult = new char[len];
		int offset = getOffestByBase(base);
		if(offset == -1) {
			throw new RuntimeException("指定的进制错误");
		}
		//do... whlie()保证至少执行一次,这样保证num==0的情况下也有结果
		do{
			int temp = num & (base-1);
			//使用temp作为角标到表中查找对应的16进制字符
			hexResult[pos--] = baseTable[temp];
			// 取下一组4个比特位的数
			num = num >>> offset;
		} while(num != 0);
		
		return hexResult;
	}

	private static int getOffestByBase(int base) {
		switch(base) {
			case 2: return Base.binary.offset;
			case 8: return Base.octal.offset;
			case 16: return Base.hex.offset;
		}
		return -1;
	}
}

 

 

 开发中这样使用进制转换

public static void main(String[] args) {
		int num = 60;
		//转为2进制
		System.out.println(Integer.toBinaryString(num));
		//转为8进制
		System.out.println(Integer.toOctalString(num));
		//转为16进制
		System.out.println(Integer.toHexString(num));
	}