一、数组

  • 数组是一种确定大小的存储同种数据的容器;
  • 需要牢牢掌握初始化和遍历方法,特别是两种遍历方式

1. 简介

  • 数组是一个存放多个数据的容器;
  • 数据是同一种类型
  • 所有的数据是线性规则排列;
  • 可通过位置索引来快速定位访问数据;
  • 需要明确容器的长度。

广义上说,以前定义的变量也可以理解为一种容器,就比如

int a = 5;

a实际上就是一种容器,里面放着数字5。

2. 定义与初始化

  • 定义:
int a[];//可以用C的方式来定义一个数组;

    int[] a;//Java中更推荐用这种方式来定义;
    //此时还没有new操作,a实际上是null(相当于空指针),不知道内存位置
  • 初始化:
int[] a = new int[5];//表明开辟了一个大小为5个int字节的数组,
    //数组内元素默认为0;

    int[] b = new int[]{1,2,3};
    int[] b = {1,2,3};//这两种初始化方式等价,都是用穷举的方式;

注意在声明一个数组时,并没有分配内存,此时不要指定大小,下面是错误示例;

int a[5];//error int[5] b;//error int[5] c = new int[5];//error

3. 数组索引

  • 数组的length属性标识数组的长度
public class LengthTest {

	    public static void main(String[] args) {
		    int[] a = new int[5];
		    System.out.println("数组长度:" + a.length);
	        }
        }
    /** 输出的结果是“数组长度:5” */
  • 数组访问时不能越界,否则会报ArrayIndexOutOfBoundsException异常

4. 数组遍历

  • for循环:这个都会,通常需要注意索引位置
  • for-each语句:
public class LengthTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {1,3,5,7,9};
		
		for(int i = 0; i < a.length; i++) {
			System.out.println(a[i]);
		}
		
		System.out.println("=================");
		
		for(int e: a) {
			System.out.println(e);
		    }
		/** 两者结果完全相同,for-each语句相比上面的语句
        不存在也不会出现越界访问,而且更简洁*/

	    }

    }

5. 多维数组(仅介绍二维)

  • 定义:
1. int a[][] = new int a[2][3];
    /** 上面表示的是一种 两行三列 的数组*/

计算机实际存储时,是按照行一个一个存储的,也就是说二维数组在内存中实际上
是线性的结构;比如上面的a[2][3],会先存储a[0][3],再接在后面存储a[1][3]。

实际在遍历二维数组中也更推荐按行逐个遍历,如果按列进行遍历实际上性能会差很多。

2. /** 对于不规则的二维数组,可以按照下面的方式定义 */

    int b[][];
    b = new int b[3][];
    b[0] = new int[3];
    b[1] = new int[4];
    b[2] = new int[5];
  • 遍历:
public class A {
	
	public static void main(String[] args) {
		
		int a[][];
		int k = 0;
		a = new int[3][];
		a[0] = new int[3];
		a[1] = new int[4];
		a[2] = new int[5];
		
		for(int i = 0; i < a.length; i++) {//二维数组中a.length表示的是整个数组的行数
			for(int j = 0; j < a[i].length ;j++) {//每一行的长度a[i].length
				a[i][j] = k++;
				    }
		    }
		for(int[] items: a) {//可以把二维数组理解成复合的数组,相当于items[]数组的每一个元素都是一个item[]数组
			for(int item: items) {
				System.out.println(item);
			    }
		    }
		
	    }
    }

for-each循环的逻辑:

for(数据类型 变量名 :数组名) {//变量名可以自定义 含有变量名的语句; }

二、 JCF(Java Collection Frame,java容器框架)

类似于C++中的STL,Standard Template Library,标准模板库

1. 简介

  • 容器:能够存放数据的空间结构;
  • 数组/多维数组:只能线性存放数据;
  • 列表/散列集/树/···
  • 容器框架:为表示和操作容器而规定的一种标准体系结构;

在数据结构课程中我们会学习对应的数据组织方式,以及如何存储、操作这些数据;
实际应用中Java将这些逻辑结构以及对应的代码封装起来,提供接口供人使用,这样
使用者就不必十分清楚数据结构的具体实现过程,只要知道如何使用就可以。

  • 优点:提高了数据存储效率,避免程序员重复劳动。

java 数组 放入list java 数组和list_System

三、 列表List

  • ArrayList/LinkedList/Vector
  • 同步采用Vector
  • 非同步情况下,根据数据操作特点选取ArrayList/LinkedList

1. ArrayList用法

  • 简介:
  • 基于数组实现,不支持同步;
  • 可以按照索引访问,方便查询,不方便移动;
  • 可以实现动态扩容,增大容量的50%;
  • 常见用法:
import java.util.ArrayList;
import java.util.Iterator;

public class ArrayListTest {

	public static void main(String[] args) {
		ArrayList<Integer> a = new ArrayList<Integer>();
		//ArryList<Integer> a是泛型表示,意思是a这个数据结构里只能容纳Integer
		//的对象,其他的对象无法放入
		a.add(3);
		a.add(2);
		a.add(1);
		a.add(4);
		a.add(5);
		a.add(6);
		a.add(new Integer(6));
		/** 
		 * ArrayList只能装对象,当add(3)时,会自动将普通int变量3
		 * 自动装箱为Integer(3)的对象,然后放入ArrayList容器中。
		 * */
		
		System.out.print("The third element is");
		System.out.println(a.get(3));//按索引访问,3表示第四个元素
		a.remove(3);//删除第四个元素,后面元素往前挪动
		a.add(3,9);//将9插入到第3个元素,后面元素往后挪动
		
		System.out.println("========遍历方法======");
		
		ArrayList<Integer> test = new ArrayList<Integer>(100000);
		for(int i = 0; i < 100000; i++) {
			test.add(i);
		}
		
		traverseByIterator(test);
		traverseByIndex(test);
		traverseByFor(test);
		
		
	}
	
	public static void traverseByIterator(ArrayList<Integer> a) {
		long startTime = System.nanoTime();
		
		System.out.println("========迭代器遍历========");
		
		Iterator<Integer> iter1 = a.iterator();
		while(iter1.hasNext()) {
			iter1.next();
		}
		long endTime = System.nanoTime();
		long duration = endTime - startTime;
		System.out.println(duration + "纳秒");
		
	}
	public static void traverseByIndex(ArrayList<Integer> a) {
		long startTime = System.nanoTime();
		
		System.out.println("========索引遍历========");
		
		for(int i = 0; i < a.size(); i++) {//size()方法可以得出数据结构的大小;
			a.get(i);
		}
		long endTime = System.nanoTime();
		long duration = endTime - startTime;
		System.out.println(duration + "纳秒");
		
	}
	public static void traverseByFor(ArrayList<Integer> a) {
		long startTime = System.nanoTime();
		
		System.out.println("========for-each遍历========");
		
		for(Integer item : a) {//数据结构a中的元素是Integer类型的变量;
			
		}
		long endTime = System.nanoTime();
		long duration = endTime - startTime;
		System.out.println(duration + "纳秒");	
		
	}
	
}

运行结果如下:

java 数组 放入list java 数组和list_数组_02

看得出来迭代器方法和随机索引速度差不多,for-each方法速度最快。

2. LinkedList用法

  • 简介:
  • 双向链表实现的列表,不支持同步;
  • 可被当做堆栈、队列和双端队列进行操作;
  • 顺序访问搞笑,随机访问较差,中间插入和删除高效;
  • 适用于经常变化的数据;
  • 常见用法:
import java.util.Iterator;
import java.util.LinkedList;

public class LinkedListTest {
	
	public static void main(String[] args) {
		LinkedList<Integer> link = new LinkedList<Integer>();
		link.add(3);
		link.add(2);
		link.add(5);
		link.add(6);
		link.add(6);
		System.out.println("link's size is: "+ link.size());
		link.addFirst(9);//在头部增加9
		link.add(3, 10);//将10插入到第四个元素,之前第四个及以后元素往后挪动
		link.remove(3);//将第四个元素删除
		
		for(Integer item: link) {
			System.out.println(item.toString());
		}
		
		System.out.println("=========遍历测试========");
		
		LinkedList<Integer> link2 = new LinkedList<Integer>();
		for(int i = 0; i < 100000; i++) {
			link2.add(i);
		}
		
		traverseByIterator(link2);
		traverseByIndex(link2);
		traverseByFor(link2);

	}
	
	public static void traverseByIterator(LinkedList<Integer> a) {
		long startTime = System.nanoTime();
		
		System.out.println("========迭代器遍历========");
		
		Iterator<Integer> iter1 = a.iterator();
		while(iter1.hasNext()) {
			iter1.next();
		}
		long endTime = System.nanoTime();
		long duration = endTime - startTime;
		System.out.println(duration + " 纳秒");
	}
	public static void traverseByIndex(LinkedList<Integer> a) {
		long startTime = System.nanoTime();
		
		System.out.println("=========随机索引遍历============");
		for(int i = 0; i < a.size(); i++) {
			a.get(i);
		}
		
		long endTime = System.nanoTime();
		long duration = endTime - startTime;
		System.out.println(duration + " 纳秒");
		
	}
	public static void traverseByFor(LinkedList<Integer> a) {
		long startTime = System.nanoTime();
		
		System.out.println("=========for-each循环遍历============");
		for(Integer item: a) {
			
		}
		
		
		long endTime = System.nanoTime();
		long duration = endTime - startTime;
		System.out.println(duration + " 纳秒");
		
	}
}

运行结果如下:

java 数组 放入list java 数组和list_System_03


上面的程序整体上和ArrayList的相同,可以看出LinkedList类的随机索引遍历速度最慢。

性能和另外两个相差3个数量级,for-each循环遍历速度最快。

3. vector

  • 简介:
  • 和ArrayList类似,可变数组实现的列表
  • vector同步,适合在多线程下使用;
  • 原先不属于JCF,属于Java最早的数据结构,性能较差;
  • 从jdk1.2开始,Vector被重写,并纳入到JCF;
  • 官方文档建议在非同步情况下,优先采用ArrayList;