Java——集合

1.集合中主要接口的概述

List接口、 Set接口、 Map接口、 Collection接口主要特征:

①Collection接口是List接口和Set接口的父接口,通常情况下不被直接使用

②List接口实现了Collection接口,List接口允许存放重复的对象,按照对象的插入顺序排列

③Set接口实现了Collection接口,Set接口不允许存放重复的对象,按照自身内部的排序规则排列

④Map接口以键值对(key-value)的形式存放对象,其中键对象不可以重复,值对象可以重复,按照自身内部的排序规则排序

2.Collection接口

Collection接口定义的常用方法如下表所示:

(1)使用addAll()方法向集合中添加对象。
public static void main(String[] args) {
		String a = "A";
		String b = "B";
		String c = "C";

		Collection<String> list = new ArrayList<String>();
		list.add(a);   // 通过add(E obj)方法添加指定对象到集合中
		list.add(b);

		Collection<String> list2 = new ArrayList<String>();
		list2.addAll(list);   // 通过addAll(Collection<? extends E> col)方法添加指定集合中的所有对象到该集合中
		list2.add(c);

		Iterator<String> it = list2.iterator(); // 通过iterator()方法序列化集合中的所有对象
		while (it.hasNext()) {
			String str = it.next(); // 因为对实例it进行了泛化,所以不需要进行强制类型转换
			System.out.println(str);
		}
	}
(2)使用removeAll()方法从集合中移除对象
public static void main(String[] args) {
		String a = "A", b = "B", c = "C";
		Collection<String> list = new ArrayList<String>();
		list.add(a);
		list.add(b);
		Collection<String> list2 = new ArrayList<String>();
		list2.add(b);
		list2.add(c);

		// 通过removeAll()方法从该集合中移除同时包含在指定集合中的对象,并获得返回信息
		boolean isContains = list.removeAll(list2);
		System.out.println(isContains);

		Iterator<String> it = list.iterator();
		while (it.hasNext()) {
			String str = it.next();
			System.out.println(str);
		}
	}

(含list2.add(b);语句)                           (不含list2.add(b);语句)

(3)使用toArray(T[] t)方法用来获得一个包含所有对象的指定类型的数组。
注意:toArray(T[] t)方法的入口参数必须为数组类型的实例,并且必须已经被初始化,它用来指定欲获得数组的类型,如果对调用toArray(T[] t)方法的实例进行了泛化,还要求入口参数的类型必须符合泛化类型。

public static void main(String[] args) {
		String a = "A", b = "B", c = "C";
		Collection<String> list = new ArrayList<String>();
		list.add(a);
		list.add(b);
		list.add(c);
		String strs[] = new String[1]; // 创建一个String型数组
		String strs2[] = list.toArray(strs); // 获得一个包含所有对象的指定类型的数组
		for (int i = 0; i < strs2.length; i++) {
			System.out.println(strs2[i]);
		}
	}

3.List集合

①List包括List接口以及List接口的所有实现类。因为List接口实现了Collection接口,所以List接口拥有Collection接口提供的所有常用方法,又因为List是列表类型,所以List接口还提供了一些适合于自身的常用方法,如下表所示:

List接口的常用实现类有ArrayList(数组结构保存对象)和LinkedList(链表结构保存对象),在使用List集合时,通常情况下声明为List类型,实例化时根据实际情况的需要,实例化为ArrayList或LinkedList,例如:

  • 数组结构的优点是便于对集合进行快速的随机访问,如果经常需要根据索引位置访问集合中的对象,使用由ArrayList类实现的List集合的效率较好。
  • 链表结构的优点是便于向集合中插入和删除对象,如果经常需要向集合中插入对象,或者从集合中删除对象,使用由LinkedList类实现的List集合的效率较好。
(1)add(int index, Object obj)方法和set(int index, Object obj)方法
注意:索引值都是从0开始
public static void main(String[] args) {
		String a = "A", b = "B", c = "C", d = "D", e = "E";
		List<String> list = new LinkedList<String>();
		list.add(a);
		list.add(e);
		list.add(d);
		list.set(1, b); // 将索引位置为1的对象e修改为对象b
		list.add(2, c); // 将对象c添加到索引位置为2的位置
      //遍历List集合
		Iterator<String> it = list.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}
	}

提示:因为List集合可以通过索引位置访问对象,所以还可以通过for循环遍历List集合。因此上面遍历集合的代码可以用下替换:
for(int i=0;i<list.size();i++)
{system.out.println(list.get(i);}

(2)indexOf(Object obj)方法和lastIndexOf(Object obj)方法
注意:前者是获得指定对象的最小的索引位置,后者是获得指定对象的最大的索引位置,前提条件是指定的对象在List集合中具有重复的对象,否则如果在List集合中有且仅有一个指定的对象,则通过这两个方法获得的索引位置是相同的。
public static void main(String[] args) {
		String a = "A", b = "B", c = "C", d = "D", repeat = "Repeat";
		List<String> list = new ArrayList<String>();
		list.add(a); // 索引位置为 0
		list.add(repeat); // 索引位置为 1
		list.add(b); // 索引位置为 2
		list.add(repeat); // 索引位置为 3
		list.add(c); // 索引位置为 4
		list.add(repeat); // 索引位置为 5
		list.add(d); // 索引位置为 6
		System.out.println(list.indexOf(repeat));
		System.out.println(list.lastIndexOf(repeat));
		System.out.println(list.indexOf(b));
		System.out.println(list.lastIndexOf(b));
	}

3.1使用LinkedList类

LinkedList类还根据采用链表结构保存对象的特点,提供了几个专有的操作集合的方法,如下表所示。

4.Set集合

Set集合包括Set接口以及Set接口的所有实现类。因为Set接口实现了Collection接口,所以Set接口拥有Collection接口提供的所有常用方法。

4.1  使用HashSet类

  • 由HashSet类实现的Set集合的优点是能够快速定位集合中的元素。
  • Set集合中的对象是无序的(这里所谓的无序,并不是完全无序,只是不像List集合那样按对象的插入顺序保存对象)例如下面的例子,遍历集合输出对象的顺序与向集合插入对象的顺序并不相同。
(1)首先新建Person类,该类需要重新实现equals() 方法和hashCode() 方法,以保证对象标识的唯一性和存储分布的合理性。
public class Person {

	private String name;
	private long id_card;

	public Person(String name, long id_card) {
		this.name = name;
		this.id_card = id_card;
	}

	public long getId_card() {
		return id_card;
	}

	public void setId_card(long id_card) {
		this.id_card = id_card;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int hashCode() { // 实现 hashCode() 方法
		final int PRIME = 31;
		int result = 1;
		result = PRIME * result + (int) (id_card ^ (id_card >>> 32));
		result = PRIME * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	public boolean equals(Object obj) { // 实现 equals() 方法
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final Person other = (Person) obj;
		if (id_card != other.id_card)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
}
(2)编写测试类,初始化Set集合并遍历输出到控制台
public class Example {
	public static void main(String[] args) {
		Set<Person> hashSet = new HashSet<Person>();
		hashSet.add(new Person("马先生", 220181));
		hashSet.add(new Person("李先生", 220186));
		hashSet.add(new Person("王小姐", 220193));
		Iterator<Person> it = hashSet.iterator();
		while (it.hasNext()) {
			Person person = it.next();
			System.out.println(person.getName() + "  " + person.getId_card());
		}
	}
}

 

提示:如果既想保留HashSet类快速定位集合中对象的优点,又想让集合中的对象按插入的顺序保存,可以通过HashSet类的子类LinkedHashSet实现Set集合

即将    Set<Person> hashSet = new HashSet<Person>(); 替换为Set<Person> hashSet = new LinkedHashSet<Person>();

4.2  使用TreeSet类

headSet()、subSet()和tailSet()
(1)首先新建Person类,由TreeSet类实现的Set集合要求该类必须实现java.lang.Comparable接口,这里实现的排序方式为按编号升序排列 
public class Person implements Comparable {

	private String name;
	private long id_card;

	public Person(String name, long id_card) {
		this.name = name;
		this.id_card = id_card;
	}

	public long getId_card() {
		return id_card;
	}

	public void setId_card(long id_card) {
		this.id_card = id_card;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int compareTo(Object o) { // 默认按编号升序排序
		Person person = (Person) o;
		int result = id_card > person.id_card ? 1 : (id_card == person.id_card ? 0 : -1);
		return result;
	}
}
(2)然后编写测试类
public class Example {
	public static void main(String[] args) {
		Person person1 = new Person("马先生", 220181);
		Person person2 = new Person("李先生", 220186);
		Person person3 = new Person("王小姐", 220193);
		Person person4 = new Person("尹先生", 220196);
		Person person5 = new Person("王先生", 220175);
		TreeSet<Person> treeSet = new TreeSet<Person>();
		treeSet.add(person1);
		treeSet.add(person2);
		treeSet.add(person3);
		treeSet.add(person4);
		treeSet.add(person5);

		System.out.println("初始化的集合:");
		Iterator<Person> it = treeSet.iterator();
		while (it.hasNext()) { // 遍例集合
			Person person = it.next();
			System.out.println("------ " + person.getId_card() + "  "+ person.getName());
		}

		System.out.println("截取前面部分得到的集合:");
		it = treeSet.headSet(person1).iterator();// 截取在集合中排在马先生(不包括)之前的人
		while (it.hasNext()) {
			Person person = it.next();
			System.out.println("------ " + person.getId_card() + "  "+ person.getName());
		}

		System.out.println("截取中间部分得到的集合:");
		// 截取在集合中排在马先生(包括)和王小姐(不包)之间的人
		it = treeSet.subSet(person1, person3).iterator();
		while (it.hasNext()) {
			Person person = it.next();
			System.out.println("------ " + person.getId_card() + "  "+ person.getName());
		}

		System.out.println("截取后面部分得到的集合:");
		it = treeSet.tailSet(person3).iterator(); // 截取在集合中排在王小姐(包括)之后的人
		while (it.hasNext()) {
			Person person = it.next();
			System.out.println("------ " + person.getId_card() + "  "+ person.getName());
		}
	}
}

5.Map集合

Map包括Map接口以及Map接口的所有实现类。由Map接口定义的常用方法如下表所示。

Map接口的常用实现类有HashMap和TreeMap,HashMap类实现的Map集合对于添加和删除映射关系更高效。TreeMap中的映射关系存在一定的顺序,在遍历集合时是有序的。

Map集合允许值对象为null,并且没有个数限制,所以当get()方法的返回值为null时,可能有两种情况,一种是在集合中没有该键对象,另一种是该键对象没有映射任何值对象,即值对象为null。因此,在Map集合中不应该利用get()方法来判断是否存在某个键,而应该利用containsKey()方法来判断。

5.1使用HashMap类

HashMap类实现了Map接口,由HashMap类实现的Map集合,允许以null作为键对象,但是因为键对象不可以重复,所以这样的键对象只能有一个。如果经常需要添加、删除和定位映射关系,建议利用HashMap类实现Map集合,不过在遍历集合时,得到的映射关系是无序的。

5.2使用TreeMap类

TreeMap类不仅实现了Map接口,还实现了Map接口的子接口java.util.SortedMap。由TreeMap类实现的Map集合,不允许键对象为null,因为集合中的映射关系是根据键对象按照一定顺序排列的,TreeMap类通过实现SortedMap接口得到的方法如下表所示。

在添加、删除和定位映射关系上,TreeMap类要比HashMap类的性能差一些,但是其中的映射关系具有一定的顺序,如果不需要一个有序的集合,则建议使用HashMap类;如果需要进行有序的遍历输出,则建议使用TreeMap类,在这种情况下,可以先使用由HashMap类实现的Map集合,在需要顺序输出时,再利用现有的HashMap类的实例,创建一个具有完全相同映射关系的TreeMap类型的实例。

(1)Person类
public class Person {
	private String name;
	private long id_card;

	public Person(String name, long id_card) {
		this.name = name;
		this.id_card = id_card;
	}

	public long getId_card() {
		return id_card;
	}

	public void setId_card(long id_card) {
		this.id_card = id_card;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
(2)测试类
public class Example {
	public static void main(String[] args) {
		Person person1 = new Person("马先生", 220181);
		Person person2 = new Person("李先生", 220193);
		Person person3 = new Person("王小姐", 220186);

		Map<Number, Person> map = new HashMap<Number, Person>();
		map.put(person1.getId_card(), person1);
		map.put(person2.getId_card(), person2);
		map.put(person3.getId_card(), person3);
		System.out.println("由HashMap类实现的Map集合,无序:");
		for (Iterator<Number> it = map.keySet().iterator(); it.hasNext();) {
			Person person = map.get(it.next());
			System.out.println(person.getId_card() + " " + person.getName());
		}

		System.out.println("由TreeMap类实现的Map集合,键对象升序:");
		TreeMap<Number, Person> treeMap = new TreeMap<Number, Person>();
		treeMap.putAll(map);
		for (Iterator<Number> it = treeMap.keySet().iterator(); it.hasNext();) {
			Person person = treeMap.get(it.next());
			System.out.println(person.getId_card() + " " + person.getName());
		}

		System.out.println("由TreeMap类实现的Map集合,键对象降序:");
		TreeMap<Number, Person> treeMap2 = new TreeMap<Number, Person>(
				Collections.reverseOrder()); // 初始化为反转排序
		treeMap2.putAll(map);
		for (Iterator it = treeMap2.keySet().iterator(); it.hasNext();) {
			Person person = (Person) treeMap2.get(it.next());
			System.out.println(person.getId_card() + " " + person.getName());
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值