黑马程序员-java集合

------- android培训java培训、期待与您交流! ----------

1.java集合概要
什么是集合,集合就像一个数组,里面装的是一大批对象,但是数组是有长度限制的,在学集合前,我们只能通过构建对象数组来对一大批对象进行操作,学习集合后,我们就可以根据不同的数据结构来完成对动态对象数组的操作。
首先我们来看一下数组和集合的区别
1.数组创建时必须指定数组的大小,集合就不需要,可以把集合理解成可以自动调整自身大小的动态的数组
2.数组可以装基本数据类型,也可以装引用数据类型,也就是对象,而集合中只能装引用型数据类型,就算你装一个基础数据类型后,也会自动帮你转成基础类型的包装类对象
3.数组的数据结构式线性序列,而集合的数据结构有很多种,比如哈希表,红黑树,线性序列,链表结构,等
4.数组的功能没有集合强大

集合框架的主要接口和类

Collection(接口)
           |-------------List(接口)
                    |-------------ArrayList(类)
                    |-------------LinkedList(类)
           |-------------Set(接口)
                    |-------------HashSet(类)
                             |-------------LinkedHashSet(类)
                    |-------------SortedSet(接口)
                             |-------------TreeSet(类)
           |-------------Queue(接口)
                    |-------------PriorityQueue(类)
                    |-------------LinkedList(类)


Map(接口)

   |-------------HashMap(类)

            |-------------LinkedHashMap(类)

   |-------------SortedMap(接口)

            |-------------TreeMap(类)

java.util包中还有很多以 abstract 开头的抽象类,在实际开发中没什么用,在上面的层次结构图中我就不列举了
Collection:是存放一组单个对象的最高的父接口,此接口中声明了 List 和 Set 接口的共性方法
其主要方法有
01.public boolean add(E e) //向集合中插入对象
02.public boolean addAll(Collection<? extends E> c)//将一个集合中的内容插入进来,有关于尖括号中的内容,是jdk1.5之后心增加的泛型,后文将对其详细介绍
03.public void clean() //清空此集合中的所有元素
04.public boolean contains(Object o) //判断该对象是否在当前集合中
05.public boolean containsAll(Collection<?>) //判断一组对象是否在当前集合中
06.public boolean equals(Object o) //判断该对象是否与当前对象相等
07.public int hashCode() //返回一个哈希值
08.public boolean isEmpty()  //判断集合是否为空,如果为空,返回true
09.public Iterator<E> iterator() //返回一个实现了Iterator接口的对象,该对象用于便利集合中的对象
10.public boolean remove(Object o) //删除指定对象,
11.public boolean removeAll(Collection<?> c) //删除一组元素
12.public boolean retainAll(Collection<?> c) //求交集,仅保留c和当前集合对象中都存在的元素
13.public int size() //求出集合的大小
14.public Object[] toArray() //将一个集合变为对象数组
15.public <T> T[] toArray(T[] a) //返回一个指定对象类型的数组(该方法是泛型方法)
在开发中一般很少使用Collection,而是使用继承了Collection的子接口,主要是List和Set,具体要使用那种接口和那种类,要根据项目需求来定,为什么会出现这么多容器,是因为
每一种容器对应的存储数据的方式不同,这个存储方式就是数据结构




2.List接口
List接口和Set接口的主要区别在于:实现了List接口的子类容器中所装的对象是有序的且可以重复的,而实现了Set接口的子类容器中所装的对象是无序且不可以重复的,咱么先看List
List接口特有的方法有
01.public void add(int index,E element) //在指定的角标位置上添加元素
02.public boolean addAll(int index,Collection<? extends E> c)//在指定的角标位置上增加一组元素
03.public E get(int index) //返回指定位置上的元素
04.public int indexOf(Object o) //返回该对象在容器中的位置
05.public int lastIndex(Object o) //返回该元素在此容器中最后出现的位置,如果该元素不存在,则返回-1
06.public ListIterator<E> listIterator() //返回一个实现了ListIterator接口的对象
07.public E remove(int index) //按指定的位置删除元素
08.public List<E> subList(int fromIndex, int toIndex)//截取子集合(包括fromIndex,不包括toIndex)
09.public E set(int index, E element) //替换指定位置的元素
实现了List接口的类主要有 LinkedList , ArrayList , Vector,它们的区别如下
LinkedList:底层是用链表实现的数据结构,采用异步处理方式,效率高,添加删除元素快,取得,修改元素慢
ArrayList:底层是采用队列(就像数组那样)的数据结构,采用异步处理方式,取得,修改元素快,添加删除元素慢
Vector:元老级人物,jdk1.0时就推出了,采用同步处理方式,性能低,效率慢,还能使用 Enumeration(可以说是 Iterator 的前生) 进行迭代输出。
集合中迭代器的使用
实例1

/*
 * ArrarList便利容器的四种方式
 */

import java.util.*;

public class TestArrayIterator {

	public static void main(String[] args) {
		
		//创建ArrayList对象
		List a1 = new ArrayList();
		//添加元素
		a1.add("hello001");
		a1.add("hello001");
		a1.add("hello004");
		a1.add("hello003");
		a1.add(null);
		
/*		for(int i = 0; i < a1.size(); i++) {	//第一种方式,因为没使用泛型,所以要强制转型,便利数据的第一种方式,使用for循环
			String str = (String)a1.get(i);		
			System.out.println(str);
		}*/		
		
/*		Iterator i1 = a1.iterator();	//第二种方式,使用Iterator迭代器
		while(i1.hasNext()) {
			String str = (String)i1.next();
			System.out.println(str);
		}*/
		
/*		while(!a1.isEmpty()) {		//第三种方式,该方法利用了remove方法特性,该方法删除元素前,先将该元素作为返回值返回
			int i = 0;
			String str = (String)a1.remove(i);
			System.out.println(str);
			i++;
		}*/
		
		ListIterator i1 = a1.listIterator();	//第四种方式,可以使用ListIterator接口,可以使用正序和逆序
		while(i1.hasNext()) {
			String str = (String)i1.next();
			//System.out.println(str);
		}
		while(i1.hasPrevious()) {
			String str = (String)i1.previous();
			System.out.println(str);
		}
	}
}

从上面这段小程序中可以看出ArrayList容器的一些特性
1.能够添加null值
2.重复的元素也能加入容器
3.从容器中取出数据时,怎么添加的就怎么取出,可见是有序的
但是要怎样使一个ArrayList容器只能填入不同的元素,看下面的例子
实例2

/*
 * 用于得到一个不能装一个重复元素的容器
 */

import java.util.*;

public class UniqueElement {

	public static void main(String[] args) {
		List l = new ArrayList();
		//向容器中添加元素
		l.add(new Person("leo", 15));
		l.add(new Person("john", 17));
		l.add(new Person("smith", 15));
		l.add(new Person("jack", 13));
		l.add(new Person("leo", 15));
		List al = UniqueElement.getNewArrayList(l);
		Iterator i1 = al.iterator();	
		while(i1.hasNext()) {
			Person p = (Person)i1.next();
				System.out.println(p.getName() + "---" + p.getId());
		}
	}

	// 定义一个静态方法,用于得到一个没有重复元素的容器
	public static List getNewArrayList(List l) {	
		List newAl = new ArrayList();
		Iterator i1 = l.iterator();
		while(i1.hasNext()) {
			Object obj = i1.next();
			if(!newAl.contains(obj)) {
				newAl.add(obj);
			}
		}
		return newAl;
	}
}
//自定义Person类
class Person {
	
	private String name;
	private int id;
	
	Person(String name, int id) {
		this.name = name;
		this.id = id;
	}
	
	public String getName() {
		return name;
	}

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

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}
	//重写equals方法
	public boolean equals(Object obj) {
		if(!(obj instanceof Person)) {
			throw new RuntimeException("不是Person对象不能比较");
		}
		Person p = (Person)obj;
		if(this.name.equals(p.name) && this.id == p.id) {
			return true;
		}
		return false;
	}
}

可以看出ArrayList内部判断是否包含同一个元素,用的是equals方法
                
LinedList的使用
实例3

import java.util.*;

public class TestLinkedList {

	public static void main(String[] args) {
		LinkedList ll = new LinkedList();
		for(int i = 1; i < 11; i++) {
			ll.offerFirst("myElement" + i);
		}
		while(!ll.isEmpty()) {
			System.out.println(ll.pollFirst());
		}
		System.out.println(ll.pollLast());		// 在jdk1.6之前用的是remove,get方法,jdk1.6后出现了poll,peek,offer取代了原来的方法
												//如果使用原来的方法,当容器为空时,会抛出NoSushElement,新方法会直接返回null;												
	}

}

在使用 LinkedList 容器对象时应注意jdk1.6之后提供的新方法。

Vector 的使用
实例4

import java.util.*;
public class TestVector {

	public static void main(String[] args) {
		Vector v = new Vector();
		for(int i = 0; i < 10; i++) {
			v.add(1 + i);
		}
		Enumeration e = v.elements();
		while(e.hasMoreElements()) {
			System.out.println(e.nextElement());
		}
	}
}

此接口的功能与 Iterator 接口的功能是重复的。此外,Iterator 接口添加了一个可选的移除操作,并使用较短的方法名。新的实现应该优先考虑使用 Iterator 接口而不是 Enumeration接口


总结
实现了 List 接口的集合能装重复的元素(包括null),元素是有序排列的,ArrayList 和 LinkedList 用哪个,这取决你的需求,如果你频繁的增加元素的话,并且在中间添加,还有就是
频繁的删除元素,建议你使用 LinkedList ,如果只是简单的获取,和修改建议使用 ArrayList, ArrayList 底层的数据结构是线性序列,所以元素在内存中是一块(元素之间相互连成一块)的
,可以直接定位过去,而 LinkedList 则是分布式的.只能通过找到第一个元素,之后通过第一个元素才能找到第二个元素,以此类推.

3.set接口
实现了set接口的子类主要有 HashSet 和 TreeSet
Set 接口的定义与 List 并没有太大区别, Set 接口的主要方法与 Collection 是一致的,但是 Set 接口比 Collection 更加严格了,不能增加重复元素,且是无序的
HashSet的使用
HashSet 底层是采用哈希表进行数据存储的,在 Object 类中用一个方法 public int hashCode() 该方法可以用于获取所有对象的哈希值
实例5

import java.util.*;
public class TestHashSet {

	public static void main(String[] args) {
		//创建一个HashSet集合,并向其中添加元素
		Set mySet = new HashSet();
		for(int i = 0; i < 10; i++) {
			mySet.add("hello" + i);
		}
		mySet.add(null);
		mySet.add(null);
		Iterator i = mySet.iterator();
		try {
			Thread.sleep(50);
		} catch(InterruptedException e) {
			e.printStackTrace();
		}
		//便利元素
		while(i.hasNext()) {
			String str = (String)i.next();
			System.out.print(str + "   ");
		}
	}
}

打印的内容是null   hello8   hello9   hello6   hello7   hello4   hello5   hello2   hello3   hello1   hello0 
从上面的结果可以看出 HashSet 容器不能接收相同的元素(包括null),从取出数据中可以看出, HashSet 容器完全是无序存放的
HashSet 是不能存放相同的元素的,但怎么才算是相同的元素呢,请看下面
实例6

/*
 *用于测试HashSet容器是怎么判断重复元素的 
 */

import java.util.*;

public class TestHashSetDemo {

	public static void main(String[] args) {
		//创建HashSet集合,并向其中添加元素
		HashSet mySet = new HashSet(); 
		for(int i = 1; i < 10; i++) {
			boolean flag = mySet.add(new Person01(16 + i, "java" + i));
			System.out.println(flag);
			if(i == 9) {
				System.out.println(mySet.add(new Person01(16 + i, "java" + i)));
			}
		}
		
	}

}
//自定义Person01类,并覆写hashCode()和eequals()方法
class Person01 {
	private String name;
	private int age;
	Person01(int age, String name) {
		this.name = name;
		this.age = age;
	}
	public int hashCode() {
		System.out.println("ok");
		//return 1;
		return name.hashCode() + age*5;
	}
	public boolean equals(Object obj) {
		//System.out.println("ok11111");
		Person01 p = (Person01)obj;
		if(this.age == p.age && this.name.equals(p.name)) {
			return true;
		}
		return false;
	}
}

由打印的内容可以看出
1.在未覆写hashcode和equals方法时,打印的内容全部是true(说明一全部加入mySet容器中)
2.只覆写hashcode方法时,不管返回的是1还是不同的整数,打印的内容也全部是true
3.既覆写hashcode又覆写equals方法,最后一个元素没有添加进去
由此可得出在向HashSet容器添加元素时,首先根据hashCode方法判断是不是相同的哈希值,如果相同,则在调用equals方法判断,在未覆写equals方法时,调用的是Object中的equals方法
比较的是两个对像的地址值(两个new出来的对象的地址值不可能相同),覆写equals方法后,则根据你的设定判断两个对象是否相同

TreeSet 的使用
TreeSet 容器能对容器中的元素进行排序(不是按插入的元素顺序排序),是按自然顺序进行排序
实例7

import java.util.*;

public class TestTreeSetSort {

	public static void main(String[] args) {
		Set mySet = new TreeSet();
		for(int i = 9; i > -1; i--) {
			mySet.add("hello" + i);
		}
		//mySet.add(null);		//和HashSet不同的是HashSet容器能接受null值,TreeSet接收后会抛NullPointerException
		Iterator i = mySet.iterator();
		while(i.hasNext()) {
			System.out.print(i.next() + "  ");
		}
	}

}

打印的结果是hello0  hello1  hello2  hello3  hello4  hello5  hello6  hello7  hello8  hello9  以此可以看出
自然顺序排序是按字母a-z,数字0-9从小到大排序

TreeSet 如何存储自定义对象,以及如何比较自定义对象
TreeSet 底层是按照二叉树(红黑树)数据结构进行存储的。(有关二叉树的内容,自己去翻数据结构去,在这里不多加赘述)
只需实现 Comparable 接口并重写 compareTo 方法即可,上例小程序的 String 类也实现了 Comparable 接口,才具有比较性
实例8

/*
 * 
 * 用于测试TreeSet容器如何对元素进行排序
 */

import java.util.*;
public class TreeSetPersonElement {

	public static void main(String[] args) {
		Set mySet = new TreeSet();
		mySet.add(new Person02(15, "leo"));
		mySet.add(new Person02(15, "leo"));	
		mySet.add(new Person02(15, "linda"));
		mySet.add(new Person02(15, "jack"));
		Iterator i = mySet.iterator();
		while(i.hasNext()) {
			System.out.print(i.next() + "  ");
		}
	}

}

//该类实现了Comparable接口
class Person02 implements Comparable  {
	
/*	public boolean equals(Object obj) {
		Person02 p = (Person02)obj;
		return (this.age == p.age) && (this.name.equals(p.name));
	}*/
	public String toString() {
		return this.name + "---" + this.age;
	}
	private String name;
	private int age;
	
	public Person02(int age, String name) {
		this.age = age;
		this.name = name;
	}
	public int compareTo(Object o) {
		Person02 p = (Person02)o;
		if(this.age > p.age) {
			return 1;
		}
		if(this.age < p.age) {
			return -1;
		}
		return this.name.compareTo(p.name);
	
	}
}

实现了 Comparable 接口的自定义对象就有了自己的排序规则,再插入元素时就可以判断该元素到底能不能插入容器中,如果调用compareTo方法后返回值为0,则绝对不能插
我们现在已经能对字符串类型的数据进行 TreeSet 容器的存储,但是却是按自然顺序进行取出的,我们有没有办法将容器中的元素按自然顺序的逆序取出数据,当然可以,但是是通过
另一种方式,让容器自身具有比较性,怎样让容器自身具有比较性呢,通过特定的构造方法,请看下例
实例9

import java.util.*;
public class TestMyComparatorSet {

	public static void main(String[] args) {
		//创建一个TreeSet集合,并向其中添加元素
		Set mySet = new TreeSet(new MyComparator());
		mySet.add("java01");
		mySet.add("leo02");
		mySet.add("john04");
		mySet.add("linda03");
		boolean flag = mySet.add("leo05");
		//拿到Iterator进行元素迭代
		Iterator i = mySet.iterator();
		while(i.hasNext()) {
			System.out.print(i.next() + "  ");
		}
	}
}

//创建一个类,该类实现了Comparator接口
class MyComparator implements Comparator {

	public int compare(Object o1, Object o2) {
		String str1 = (String)o1;
		String str2 = (String)o2;
		if(str1.compareTo(str2) > 0) {
			return -1;
		}
		if(str1.compareTo(str2) < 0) {
			return 1;
		}
		return 0;
	}
	
}

打印的结果是linda03  leo05  leo02  john04  java01  
从结果中可以看出这个顺序是按 String 自然顺序的逆序进行排序的
这个小程序先让一个类实现 Comparator 接口,之后在构造 TreeSet 容器时,通过特定的构造方法,让容器一旦成功创建,就具有比较性,这样在比较对象时,就会自动覆盖掉元素本身具
有的比较性,第二种排序方式相对于第一种方式更为麻烦,但作用范围更广
泛型的基本使用
什么是泛型:泛型就是指在对象建立时不指定类中属性的具体类型,而由外部在声明及实例化对象时指定具体的类型,泛型是在jdk1.5之后新增加的
实例10

/*
 * 使用泛型前
 * 
 */
import java.util.*;
public class TestFanXing {

	public static void main(String[] args) {
		List myList = new ArrayList();
		myList.add(new Person03());
		myList.add(new Person03());
		myList.add(new Person03());
		myList.add("hello001");
		myList.add("hell0002");
		Iterator i = myList.iterator();
		while(i.hasNext()) {
			Person03 p = (Person03)i.next();
			System.out.println(p);
		}
	}
}

class Person03 {

	public static int  i = 0;
	public String toString() {
		return "i am java" + i++;
	}
	
}

程序运行结果是:
i am java0
i am java1
i am java2
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to Person03
at TestFanXing.main(TestFanXing.java:17)
在向容器中添加数据时,既添加了字符串对象,又添加了 Person03 数据,所以在取出数据时会出现 ClassCastException ,这个异常是 RuntimeException 的子类,是在运行时才会出现的
异常,编译时不会出现,而如果在创建容器对象时就用泛型来指定的话,就可以将运行时的异常拖到编译期间来l,还是那个小程序,看看加入泛型后的后果是
实例11

/*
 * 使用泛型后
 * 
 */
import java.util.*;
public class TestFanXing {

	public static void main(String[] args) {
		List<String> myList = new ArrayList<String>();
		myList.add(new Person03());
		myList.add(new Person03());
		myList.add(new Person03());
		myList.add("hello001");
		myList.add("hell0002");
		Iterator<String> i = myList.iterator();
		while(i.hasNext()) {
			//Person03 p = (Person03)i.next();
			System.out.println(p);
		}
	}

}

class Person03 {

	public static int  i = 0;
	public String toString() {
		return "i am java" + i++;
	}
}

在容器中加入泛型的操作后,代表只能向该容器添加此类的对象,否则连编译都无法通过
总结:
1.实现了Set接口的对象不能有重复元素,并且是无序的(不能以偏概全,LinkedHashSet 就是有序的),HashSet提供了快速查找对象的效率的能力,能添加null,两个或者多个就不行,他会认为
是重复的元素,不允许添加,添加进 HashSet 容器中的元素重写equals方法前必须重写hashCode方法,TreeSet 也是无序的,但是你添加元素的时候,他会把元素和集合中的元素作比较,给
他们个大小,然后按升序排列,所以打算添加进 TreeSet 集合中的元素必须自身具有比较性(实现 Comparable 接口,如果compareTo方法返回值是0,则代表元素重复,不允许添加)或者让 
TreeSet 容器具有比较性,可以通过构造方法指定.比较性的优先级是:容器比较性的优先级>元素比较性的优先级>自然排序优先级>元素扔进集合的顺序优先级.


Map 接口
上面说讲的 Collection Set List 接口都属于对一个对象的操作,而 Map 接口所操作的对象是一对对象
Map 接口常用的子类有三个,分别是 HashMap Hashtable TreeMap
HashMap 和 Hashtable 的异同
1. Hashtable ,底层是用哈希表数据结构来对数据进行存储,线程是同步的,效率低,不允许向容器中加入null键null值,无序存放,jdk1.0版本就出现了
2. HashMap ,底层是用哈希表数据结构来对数据进行存储,线程是非同步的,效率高,允许向容器中加入null键null值,无序存放,jdk1.2版本就出现了
一般在开发中建议使用 HashMap 这个类
第一种方式
HashMap 容器常用的添加数据和取出数据
实例12

/*
 *第一种取出数据的方式 
 */

import java.util.*;
public class TestHashMapDemo {

	public static void main(String[] args) {
		Map<String, String> myMap1 = new HashMap<String, String>();
		for(int i = 0; i < 10; i++) {
			myMap1.put(null, "12");
			myMap1.put("hello java", null);
		}
		Map<String, String> myMap2 = new HashMap<String, String>();
		myMap2.putAll(myMap1);
		myMap2.put("hello", "i am java00");
		myMap2.put("hello", "i am java01");
		//先拿到键的Set集合
		Set mySet = myMap2.keySet();
		Iterator<String> i = mySet.iterator();
		while(i.hasNext()) {
			//通过键拿到值
			String str = myMap2.get(i.next());
			System.out.println(str);
		}

	}
}

第二种方式
利用 Map.Entry<K,V> 这个内部接口
这个接口是 Map 的一个内部接口,因为在前面加了 static 关键字,所以可以通过、类名.Entry来使用
实现了这个接口的对象中封装了key 和 value 的映射关系
实例13

/*
 *用Entry这个内部接口的实例来取得数据 
 */

import java.util.*;
public class TestEntryDemo {

	public static void main(String[] args) {
		Map<String, String> myMap1 = new HashMap<String, String>();
		for(int i = 0; i < 10; i++) {
			myMap1.put(null, "12" + i);
			myMap1.put("hello java" + i, null);
		}
		Map<String, String> myMap2 = new HashMap<String, String>();
		myMap2.putAll(myMap1);
		myMap2.put("hello", "i am java00");
		myMap2.put("hello111", "i am java01");
		//将键值对作为一个对象扔进Set集合
		Set<Map.Entry<String, String>> myEntry = myMap2.entrySet();
		Iterator<Map.Entry<String, String>> i = myEntry.iterator();
		while(i.hasNext()) {
			//迭代取得数据
			Map.Entry e = i.next();
			System.out.println(e.getKey() + "----"+ e.getValue()); 
		}
	}
}

这个取出数据的方法相对于第一种,没那么好理解,但要求一定要掌握好,接下来,看看 TreeMap 这个容器
TreeMap 相对于 HashMap 多了个自动排序的功能,且底层是用二叉树数据结构进行数据存储的
实例14

/*
 *用于测试TreeMap的小程序 
 */
import java.util.*;
public class TestTreeSetDemo {

	public static void main(String[] args) {
		Map<String, String> myMap = new TreeMap<String, String>();
		myMap.put("01", "hello01");
		myMap.put("01", "hello04");
		//myMap.put(null, "null");
		myMap.put("05", null);
		myMap.put("02", "hello02");
		myMap.put("03", "hello01");
		Set<Map.Entry<String, String>> s = myMap.entrySet();
		Iterator <Map.Entry<String, String>> i = s.iterator();
		while(i.hasNext()) {
			Map.Entry<String, String> entry = i.next();
			System.out.println(entry.getKey() + "   " + entry.getValue());
		}
	}

}

打印的结果是
01   hello04
02   hello02
03   hello01
05   null
由此看出, TreeMap 和 HashMap 的区别是
1.在 HashMap 容器中装的元素 key 和 value 可以都为null,没关系,但是键为null的只能有一个而 TreeMap 中只允许 value 为 null(因为要比较吗,null 怎么比啊)
2.从打印的结果可以看出该容器是按 key 的自然顺序进行排序的,和 HashMap 容器的无序是有区别的
相同点是如果两个元素的 key 相同,则后加入的元素的 value 将覆盖前面的 value
实例15

/*
 *用于测试TreeMap自定义对象的排序
 */

import java.util.*;
public class TestTreeSetDemo {

	public static void main(String[] args) {
		Map<Person04, Integer> myMap = new TreeMap<Person04, Integer>(new MyCompartor());
		myMap.put(new Person04(15, "jack"), 1);
		myMap.put(new Person04(17, "smith"), 2);
		myMap.put( new Person04(17, "leo"), 3);
		myMap.put( new Person04(19, "john"), 3);
		myMap.put(new Person04(20, "smith"), 2);
/*		//myMap.put(null, "null");
		myMap.put("05", null);
		myMap.put("02", "hello02");
		myMap.put("03", "hello01");*/
		Set<Map.Entry<Person04, Integer>> s = myMap.entrySet();
		Iterator <Map.Entry<Person04, Integer>> i = s.iterator();
		while(i.hasNext()) {
			Map.Entry<Person04, Integer> entry = i.next();
			System.out.println(entry.getKey().getAge() + "  " + entry.getKey().getName()+ "   " + entry.getValue());
		}
	}

}

class MyCompartor implements Comparator<Person04> {

	public int compare(Person04 p1, Person04 p2) {
		if(p1.getName().compareTo(p2.getName()) != 0) {
			return p1.getName().compareTo(p2.getName());
		}
		return p1.getAge() - p2.getAge();
	}
	
	
}

class Person04 implements Comparable<Person04> {
	
	private String name;
	private int age;
	
	Person04(int age, String name) {
		this.name = name;
		this.age = age;
	}
	
	public String getName() {
		return this.name;
	}
	
	public int getAge() {
		return this.age;
	}

	public int compareTo(Person04 p) {
		if(this.age > p.age) {
			return 1;
		}
		if(this.age < p.age) {
			return -1;
		}
		return this.name.compareTo(p.name);
	}	
} 

原理和 TreeSet 一样,在这里就不多加赘述了


集合中的其他内容
1. Collections 的使用
此类是一个集合工具类,完全由在 collection 上进行操作或返回 collection 的静态方法组成
值得一提的是
static <T> List<T> 
 emptyList() 
          返回空的列表(不可变的)。 
static <K,V> Map<K,V> 
 emptyMap() 
          返回空的映射(不可变的)。 
static <T> Set<T> 
 emptySet() 
          返回空的 set(不可变的)。 
有这三个方法生成的对象是空集合,且不能添加元素,否则会抛出UnsupportedOperationException异常
下面通过相关的程序来演示 Collections 的常用方法
实例16

/*
 * 用于测试Collections类中常用的方法
 */
import java.util.*;
public class TestCollections {

	public static void main(String[] args) {
		List<String> mylist = new ArrayList<String>();
		mylist.add("abc");
		mylist.add("abce");
		mylist.add("iansdfsd");
		mylist.add("aaaaaaaaaa");
		mylist.add("vbvvv");

		System.out.println(mylist);
		//Collections.sort(mylist);			//利用String的自然顺序对他进行排序
		Collections.sort(mylist, Collections.reverseOrder(new MyComparator01()));			//可以通过自己指定的方式对他进行排序
		System.out.println(mylist);
		//int i = Collections.binarySearch(mylist, "abc");		//用于获取指定元素的下标
		//System.out.println(i);
		int j = Collections.binarySearch(mylist, "abc", Collections.reverseOrder(new MyComparator01()));
		System.out.println(mylist);
		System.out.println(j);
		Collections.shuffle(mylist);		//该方法能够对容器中的元素顺序进行打乱重置
		System.out.println(mylist);
	}

}

class MyComparator01 implements Comparator<String> {

	public int compare(String s1, String s2) {
		//return s1.length() - s2.length();
		return  s2.compareTo(s1);
	}
	
}

Runtime 类 和 Process
实例17
Runtime :每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。 这个类实现了单例模式
通过getRuntime()方法能得到当前 Java 应用程序相关的运行时唯一的对象

//import java.util.*;
public class TestRuntime {

	public static void main(String[] args) throws Exception {
		Runtime rt = Runtime.getRuntime();
		long l = rt.maxMemory();		//虚拟机试图使用的最大内存量,以字节为单位。
		System.out.println(l);
		Process p = rt.exec("C:\\Windows\\system32\\notepad.exe g:\\集合.java");		//让记事本打开一个文件,并返回该程序进程
		Thread.sleep(5000);
		p.destroy();		//5秒后,杀掉该进程
	}

}

Process 是一个抽象类,并没有实现此类的对象,它是由底层的操作系统直接调用的·

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值