JavaSE——集合框架

1、java集合框架所提供的接口和类全部在java.util包中;

2、集合框架是为表示和操作集合而规定的一种统一的标准体系结构;

3、集合框架包含三大块内容:对外接口,接口实现,对集合运算的算法;

4、集合框架共有三大类接口:List,Set,Map,其中List和Set是Collection的子接口;

5、Collection存储一组允许重复、无序的对象;

      Set接口继承Collection接口,存储一组不允许重复、无序的对象;

      List接口继承Collection接口,存储一组允许重复,有序的对象;

      Map接口存储一组成对的键-值对象,提供key-value的映射,其中,key不允许重复,value允许重复,都不要求有序;

      Iterator接口是负责定义访问和遍历元素的接口;

6、实现List接口的常用类有 ArrayList 和 LinkedList;

      ArrayList对数组进行了封装,实现了长度可变的数组,它的优点在于遍历和随机访问元素的效率比较高;

     LinkedList采用链表存储方式,优点在于插入、删除时效率比较高;

7、数组线性表类ArrayList包含的方法:

     boolean add(Object o):在列表末尾顺序添加元素,起始索引位置从0开始;

     void add(int index,Object o):在指定索引位置添加元素,原索引位置的元素及其后面的元素依次后移;

     Object set(int index,Object o):将指定索引位置的对象修改为o;

     int size():返回列表中的元素个数;

     Object get(int index):返回制定位置处的元素;

     boolean contains(Object o):判断列表中是否存在指定元素;

     boolean remove(Object o):从列表中删除元素;

     Object remove(int index):从列表中删除制定位置的元素,其索引位置从0开始;   

package 集合框架;

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

public class Test {

	public static void main(String[] args) {
		/**
		 * 创建宠物对象
		 */
		Pet pet1 = new Dog("欢欢", "拉布拉多");
		Pet pet2 = new Dog("大大", "萨摩耶");
		Pet pet3 = new Dog("跳跳", "柯基");
		Pet pet4 = new Dog("汤圆", "京巴");
		// 创建集合保存信息
		List<Pet> list = new ArrayList<Pet>();
		// 将对象添加到集合中
		list.add(pet1);
		list.add(pet2);
		list.add(pet3);
		list.add(0, pet4);
		// 输出删除之前集合中原始存在的元素数量,并且遍历它们
		System.out.println("删除之前共有:" + list.size() + "条狗狗!");
		System.out.println("分别是:");
		for (int i = 0; i < list.size(); i++) {
			Pet pet = list.get(i);
			System.out.println(pet.getName() + "," + pet.getStrain());
		}
		// 删除集合中下标为0的对象和pet2对象
		list.remove(0);
		list.remove(pet2);
		// 显示删除之后集合中剩余的元素数量,并且遍历它们
		System.out.println("删除之后还有:" + list.size() + "条狗狗!");
		System.out.println("分别是:");
		for (int i = 0; i < list.size(); i++) {
			Pet pet = list.get(i);
			System.out.println(pet.getName() + "," + pet.getStrain());
		}
		// 查询集合中是否包含pet4对象的信息
		if (list.contains(pet4)) {
			System.out.println("集合中包含pet1的信息!");
		} else {
			System.out.println("集合中不包含pet1的信息!");
		}
		/**
		 * 输出信息:
		 * 删除之前共有:4条狗狗! 
		 * 分别是: 
		 * 汤圆,京巴
		 * 欢欢,拉布拉多 
		 * 大大,萨摩耶 
		 * 跳跳,柯基 
		 * 删除之后还有:2条狗狗! 
		 * 分别是: 
		 * 欢欢,拉布拉多 
		 * 跳跳,柯基
		 * 集合中不包含pet1的信息!
		 */
	}

}

8、链表类LinkedList包含的方法

     LinkedList除了第7点包含的方法之外,还包含一些特殊的方法,能够更方便的执行添加、查询、删除元素操作:

     void addFirst(Object o)

     void addLast(Object o)

     解释:在列表首部或尾部添加元素;

     Object getFirst()

     Object getLast()

     解释:返回列表中的第一个或最后一个元素;

     Object removeFirst()

     Object removeLast()

     解释:删除并返回列表中第一个或最后一个元素;

package 集合框架;

import java.util.LinkedList;

public class Test {

	public static void main(String[] args) {
		/**
		 * 创建宠物对象
		 */
		Pet pet1 = new Dog("欢欢", "拉布拉多");
		Pet pet2 = new Dog("大大", "萨摩耶");
		Pet pet3 = new Dog("跳跳", "柯基");
		Pet pet4 = new Dog("汤圆", "京巴");
		Pet pet5 = new Dog("小黑", "金毛");
		// 创建集合保存信息,如果是用List接口创建的LinkedList集合,那么当调用LinkedList中特有的方法时,需要强制类型转换
		LinkedList<Pet> list = new LinkedList<Pet>();
		// 将对象添加到集合中
		list.add(pet1);
		list.add(pet2);
		list.add(pet3);
		list.addFirst(pet5);
		list.addLast(pet4);
		// 输出删除之前集合中原始存在的元素数量,并且遍历它们
		System.out.println("删除之前共有:" + list.size() + "条狗狗!");
		System.out.println("分别是:");
		for (int i = 0; i < list.size(); i++) {
			Pet pet = list.get(i);
			System.out.println(pet.getName() + "," + pet.getStrain());
		}
		// 删除集合中下标为0的对象,pet2对象之后,再删除剩余对象中的第一个和最后一个对象
		list.remove(0);
		list.remove(pet2);
		list.removeFirst();
		list.removeLast();
		// 显示删除之后集合中剩余的元素数量,并且遍历它们
		System.out.println("删除之后还有:" + list.size() + "条狗狗!");
		System.out.println("分别是:");
		for (int i = 0; i < list.size(); i++) {
			Pet pet = list.get(i);
			System.out.println(pet.getName() + "," + pet.getStrain());
		}
		// 查询集合中是否包含pet4对象的信息
		if (list.contains(pet4)) {
			System.out.println("集合中包含pet4的信息!");
		} else {
			System.out.println("集合中不包含pet4的信息!");
		}
		/**
		 * 删除之前共有:5条狗狗! 
		 * 分别是: 
		 * 小黑,金毛 
		 * 欢欢,拉布拉多 
		 * 大大,萨摩耶 
		 * 跳跳,柯基 
		 * 汤圆,京巴 
		 * 删除之后还有:1条狗狗! 
		 * 分别是: 
		 * 跳跳,柯基
		 * 集合中不包含pet4的信息!
		 */
	}
}

9、Set接口是Collection的另一个常用的子接口,Set接口常用的实现类有HashSet,因为存储的对象是无序且唯一的,所以所有的需要索引的方法,Set接口都没有

     HashSet类的常用方法:

     boolean add(Object o):如果此Set中尚未包含指定元素,则添加指定元素;

     void clear():从此Set中移除所有元素;

     int size():返回此Set中元素的数量;

     boolean isEmpty():如果此Set中不包含任何元素,则返回true;

     boolean contains(Object o):如果此Set中包含指定元素,则返回true;

     boolean remove(Object o):如果指定元素存在于此Set中,则将其移除;

package 集合框架;

import java.util.HashSet;
import java.util.Set;

public class Test {

	public static void main(String[] args) {
		/**
		 * 创建宠物对象
		 */
		Pet pet1 = new Dog("欢欢", "拉布拉多");
		Pet pet2 = new Dog("大大", "萨摩耶");
		Pet pet3 = new Dog("跳跳", "柯基");
		Pet pet4 = new Dog("汤圆", "京巴");

		Set<Pet> set = new HashSet<Pet>();

		set.add(pet1);
		set.add(pet2);
		set.add(pet3);
		set.add(pet4);

		System.out.println("现在集合中存在的狗狗数量为:" + set.size());

		set.remove(pet1);
		// 由于HashSet存储的对象是无序的,所以也就不存在索引,因此不能用普通for循环遍历
		for (Object o : set) {
			System.out.println(o);
		}

		if (set.contains(pet2)) {
			System.out.println("存在pet2的信息!");
		} else {
			System.out.println("不存在pet2的信息!");
		}
		/**
		 * 现在集合中存在的狗狗数量为:4 
		 * 宠物名字是:汤圆,品种是:京巴 
		 * 宠物名字是:跳跳,品种是:柯基 
		 * 宠物名字是:大大,品种是:萨摩耶 
		 * 存在pet2的信息!
		 */
	}
}

10、TreeSet是一个不同步的非线程安全的二叉树;

        TreeSet存储数据时,考虑以下两种情况:

        TreeSet存储基本数据类型的数据时,排序方式是按照基本数据类型的既定顺序进行排序的,会在内部调用compareTo方法对数据进行排序和检查其唯一性;

         TreeSet存储自定义的数据类型时,需要让该类或该类的直接父类实现Comparable接口,之后重写其中的compareTo方法,在重写的compareTo方法中需要重写排序方式和检查其唯一性的代码,例如:

package 集合框架;

import java.util.Set;
import java.util.TreeSet;

public class Test {

	public static void main(String[] args) {
		Pet pet1 = new Dog("小赵", "柯基");
		Pet pet2 = new Dog("小青", "萨摩");
		Pet pet3 = new Dog("小白", "金毛");
		Pet pet4 = new Dog("小金", "京巴");

		Set<Pet> set = new TreeSet<Pet>();

		set.add(pet1);
		set.add(pet2);
		set.add(pet3);
		set.add(pet4);

		for (Pet pet : set) {
			System.out.println(pet);
		}

		/**
		 * Console输出: 
		 * 宠物名字是:小白,品种是:京巴 
		 * 宠物名字是:小金,品种是:金毛 
		 * 宠物名字是:小青,品种是:萨摩 
		 * 宠物名字是:小赵,品种是:柯基
		 */
	}
}

         基本数据类型的值的排序是比较简单的,此处不再赘述,下面的代码给出的是针对汉字进行字典顺序排序的实现:

@Override
	public int compareTo(Pet pet) {
		// Collator 类是用来执行区分语言环境这里使用CHINA
		Comparator<Object> cmp = Collator.getInstance(java.util.Locale.CHINA);

		// 当宠物名字和品种都相同时,说明对象是重复的,此时直接返回0
		if (this.getName().equals(pet.getName()) && this.getStrain().equals(pet.getStrain())) {
			return 0;
		}

		// 如果名字相同,品种不同,则按照名字排序,反之,按照品种排序
		if (this.getName().equals(pet.getName()) && !(this.getStrain().equals(pet.getStrain()))) {
			String strain[] = new String[] { this.getStrain(), pet.getStrain() };
			// jdk自带对数组进行排序
			Arrays.sort(strain, cmp);
			if (strain[0].equals(this.getStrain())) {
				return -1;
			} else {
				return 1;
			}
		} else {
			String name[] = new String[] { this.getName(), pet.getName() };
			Arrays.sort(name, cmp);
			if (name[0].equals(this.getName())) {
				return -1;
			} else {
				return 1;
			}
		}
	}

11、Map接口——HashMap集合类

    (1)HashMap基本介绍

       HashMap是java中使用最为频繁的map类型,其读写效率较高,但是因为其是非同步的,即读写等操作都是没有锁保护的,所以在多线程场景下是不安全的,容易出现数据不一致的问题;在单线程场景下非常推荐使用;
       HashMap其实就是一个散列表,它是通过拉链法来解决哈希冲突的,影响HashMap性能的主要有两个参数,初始容量和加载因子,容量是可以存储的条目数量,加载因子是哈希表在存满之前,可以达到多满的一种尺度,如果哈希表中的条目数超过了当前容量与加载因子的乘积,则要对哈希表进行rehash操作,也就是重建内部数据结构,来扩大哈希表的容量;

      哈希表中的键值对都是存储在Entry数组中的;

   (2)HashMap包含四个构造函数:

       使用默认容量16,默认加载因子0.75f创建的HashMap集合;

       指定容量和加载因子创建的集合,如果指定容量小于0,指定加载因子小于0或为空,都会抛出IllegalArgumentException(不合法参数)异常,如果指定容量大于默认最大允许的容量1*2^30,则用该最大容量替换指定容量;

        仅指定最大容量的构造函数,加载因子使用默认的0.75f;

        以指定Map集合最为参数的构造函数,将会创建一个新的Map集合,将参数集合中的元素,逐个添加到新创建的集合中,创建新的Map集合的时候,会调用指定容量和加载因子的构造函数,指定的容量为:参数集合的容量或者默认容量16,两个容量相比,哪个大就用哪个容量,指定的加载因子用的是默认的0.75f,计算参数集合容量的方式为:m.size()/默认加载因子,由于需要将结果强制转换为int类型的整型值,所以有可能损失小数部分的精度,因此,需要在强制转换之后的结果基础上+1;

    (3)HashMap实现的接口:

             Cloneable接口,即实现了clone方法,作用是克隆一个HashMap对象并返回;

             Serializable接口,分别实现了串行读取和写入功能,readObject()和writeObject()方法的作用是:将HashMap的总的容量,实际容量以及所有的Entry依次读取或者写入到输出流中;

     (4)HashMap的遍历方式:

package 集合框架;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class Test {

	@SuppressWarnings("unchecked")
        //用Entry来遍历是效率最高的
	private static void getKey_Value(Map<String, String> map) {
		Iterator<?> iterator = map.entrySet().iterator();
		while (iterator.hasNext()) {
			Map.Entry<String, String> entry = (Map.Entry<String, String>) iterator.next();
			System.out.println("key是:" + entry.getKey() + ",value是" + entry.getValue());
		}
		System.out.println("--------------------------------------------------------------");
	}

	private static void getKey(Map<String, String> map) {
		Iterator<String> iterator = map.keySet().iterator();
		while (iterator.hasNext()) {
			System.out.println("键分别是:" + iterator.next());
		}
		System.out.println("--------------------------------------------------------------");
	}

	private static void getValue(Map<String, String> map) {
		Iterator<String> iterator = map.values().iterator();
		while (iterator.hasNext()) {
			System.out.println("值分别是:" + iterator.next());
		}
		System.out.println("--------------------------------------------------------------");
	}

	public static void main(String[] args) {
		// 创建集合
		Map<String, String> map = new HashMap<String, String>();
		// 存储数据
		map.put("CN", "中华人民共和国");
		map.put("RU", "俄罗斯联邦");
		map.put("FR", "法兰西共和国");
		map.put("US", "美利坚合众国");

		System.out.println("CN对应的国家是:" + map.get("CN"));
		System.out.println("目前共存储了" + map.size() + "条信息!");
		// 遍历键值对,单独遍历键,单独遍历值
		getKey_Value(map);
		getKey(map);
		getValue(map);
		// 以键判断是否存在指定的键值对,如果存在,则输出键对应值后删除该键值对映射
		if (map.containsKey("CN")) {
			System.out.println("存在指定的key,对应的国家是:" + map.get("CN"));
			map.remove("CN");
		}
		// 判断是否删除成功
		if (!map.containsKey("CN")) {
			System.out.println("删除成功!");
		}
		// 清空所有的键值对映射
		map.clear();
		// 判断是否清空成功
		if (map.isEmpty()) {
			System.out.println("已经删除所有键值对映射!");
		}
		/**
		 * 输出: 
		 * CN对应的国家是:中华人民共和国 
		 * 目前共存储了4条信息! 
		 * key是:RU,value是俄罗斯联邦 
		 * key是:CN,value是中华人民共和国
		 * key是:FR,value是法兰西共和国 
		 * key是:US,value是美利坚合众国
		 * -------------------------------------------------------------- 
		 * 键分别是:RU
		 * 键分别是:CN 
		 * 键分别是:FR 
		 * 键分别是:US
		 * -------------------------------------------------------------- 
		 * 值分别是:俄罗斯联邦
		 * 值分别是:中华人民共和国 
		 * 值分别是:法兰西共和国 
		 * 值分别是:美利坚合众国
		 * --------------------------------------------------------------
		 * 存在指定的key,对应的国家是:中华人民共和国 
		 * 删除成功! 
		 * 已经删除所有键值对映射!
		 */
	}
}

12、使用泛型集合在创建集合对象时指定集合中元素的类型,从集合中取出元素时无须进行类型强制转换,但如果把非指定类型对象放入集合,会出现编译错误;

13、对于集合有用的方法

       用数组来创建集合:

Integer arr[]= {1,2,3,4,5,6};
//asList()方法中存放的是一个对象
List<Integer> list = new ArrayList<>(Arrays.asList(arr));

      用集合来创建数组:

Integer arr2[]=new Integer[list.size()];
//将list集合中的元素复制进入数组arr2中
list.toArray(arr2);

      如果集合中的元素是可以用来比较的,如整数,双精度浮点数或者字符串(字母型字符串),则可以调用java.util.Collections中的静态方法sort进行排序:

String arr[]= {"pear","manggo","hello","zoo","pig","apple"};
List<String> list=new ArrayList<>(Arrays.asList(arr));
Collections.sort(list);
System.out.println(list);
/**
* 输出:
* [apple, hello, manggo, pear, pig, zoo]
*/

      如果是汉字类型的中文字符串,排序方式参考前面重写的compareTo()方法;

      还可以用Collections类中的max和min方法,返回集合中的最大值和最小值:

String arr[]= {"pear","manggo","hello","zoo","pig","apple"};
List<String> list=new ArrayList<>(Arrays.asList(arr));
Collections.sort(list);
System.out.println(list);
System.out.println(Collections.max(list));
System.out.println(Collections.min(list));
/**
 * 输出:
 * [apple, hello, manggo, pear, pig, zoo]
 * zoo
 * apple
 */

      还可以用Collections类中的shuffle()方法,来随机打乱集合中的元素顺序:

String arr[]= {"pear","manggo","hello","zoo","pig","apple"};
List<String> list=new ArrayList<>(Arrays.asList(arr));
Collections.shuffle(list);
System.out.println(list);
/**
 * 输出:
 * [zoo, manggo, pig, apple, hello, pear]
 */

14、使用集合实现模拟栈

        栈是限定仅在表的一端进行插入和删除运算的线性表:

       (1)通常称插入、删除的这一端为栈顶,另一端为栈底;

       (2)当表中没有元素时称为空栈;

       (3)栈是先进后出(First in Last out)的线性表,简称FILO表,也称为后进先出(LIFO);

       (4)从栈中删除元素称为退栈;

package 自定义栈类;

import java.util.ArrayList;
/**
 * @author 叶孤城
 * isEmpty:判断是否为空栈;
 * size:返回该栈目前存储的元素数量;
 * peek:获取并返回栈顶元素;
 * pop:删除栈顶元素并返回它;
 * push:添加一个新的元素
 * toString:以字符串格式输出栈信息;
 */
public class MyStrack {
	
	private ArrayList<Object> list=new ArrayList<Object>();
	
	public boolean isEmpty() {
		return list.isEmpty();
	}

	public int size() {
		return list.size();
	}
	
	public Object peek() {
		return list.get(list.size()-1);
	}
	
	public Object pop() {
		Object o = list.get(list.size()-1);
		list.remove(o);
		return o;
	}
	
	public void push(Object o) {
		list.add(o);
	}
	
	@Override
	public String toString() {
		return "Strack"+list.toString();
	}
}

下面是测试类:

package 自定义栈类;

public class Test {

	public static void main(String[] args) {
		MyStrack strack = new MyStrack();

		System.out.println("是空栈吗?" + strack.isEmpty());

		for (int i = 0; i < 5; i++) {
			int a = (int) (Math.random() * 32) + 23;
			strack.push(a + "");
		}

		System.out.println("输出栈信息:" + strack.toString());
		System.out.println("是空栈吗?" + strack.isEmpty());
		System.out.println("栈中有" + strack.size() + "个元素");
		System.out.println("栈顶元素是:" + strack.pop());
		System.out.println("现在的栈顶元素是:" + strack.peek());
		System.out.println("输出栈信息:" + strack.toString());

		/**
		 * 输出: 是空栈吗?true 
		 * 输出栈信息:Strack[42, 39, 33, 45, 50] 
		 * 是空栈吗?false 
		 * 栈中有5个元素 
		 * 栈顶元素是:50
		 * 现在的栈顶元素是:45 
		 * 输出栈信息:Strack[42, 39, 33, 45]
		 */
	}
}

      在这个例子中,ArrayList和MyStrack是一种组合关系,它定义了一个全新的类,而无须集成ArrayList中不必要和不恰当的方法;

 

 

 

 

 

 

 

阅读更多
换一批

没有更多推荐了,返回首页