017.java_Java集合框架

写的非常好的一篇文章点击打开链接

java中的集合又叫容器。他是一个对象,用来存储并管理一组其它对象。

java.util包中专门设置了一组接口和类,用以实现以不同的方式存放和管理对象的存储结构,这样的一组接口和类的设计被统称为java集合框架。

任何对象加入集合类后,自动转变为Object类型,所以在取出的时候,需要进行强制类型转换。


1.Collection接口和Iterator接口

Iterator接口

Collection接口继承Iterator接口,Iterator接口提供的iterator()方法会返回一个用于遍历集合内所有元素的迭代器,方法列表如下:

boolean hasNext()判断是否有元素可以迭代
E next()返回迭代到的下一个元素
void remove()删除迭代器返回的最后一个元素

通常情况下,你会希望遍历一个集合中的元素。例如,显示集合中的每个元素。
一般遍历数组都是采用for循环或者增强for,这两个方法也可以用在集合框架,但是还有一种方法是采用迭代器遍历集合框架,它是一个对象,实现了Iterator 接口或ListIterator接口。
迭代器,使你能够通过循环来得到或删除集合的元素。ListIterator 继承了Iterator,以允许双向遍历列表和修改元素。
使用 Java Iterator

这里通过实例列出Iterator和listIterator接口提供的所有方法。

import java.util.*;
public class IteratorTest1{
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("Hello");
list.add("World");
list.add("HAHAHAHA");
//第一种遍历方法使用foreach遍历List
for (String str : list) { //也可以改写for(int i=0;i<list.size();i++)这种形式
System.out.println(str);
}
//第二种遍历,把链表变为数组相关的内容进行遍历
String[] strArray=new String[list.size()];
list.toArray(strArray);
for(int i=0;i<strArray.length;i++) //这里也可以改写为 foreach(String str:strArray)这种形式
{
System.out.println(strArray[i]);
}
//第三种遍历 使用迭代器进行相关遍历
Iterator<String> ite=list.iterator();
while(ite.hasNext())//判断下一个元素之后有值
    {
System.out.println(ite.next());
    }
}
}
三种方法都是用来遍历ArrayList集合,第三种方法是采用迭代器的方法,该方法可以不用担心在遍历的过程中会超出集合的长度。

运行结果:

Hello
World
HAHAHAHA
Hello
World
HAHAHAHA
Hello
World
HAHAHAHA


import java.util.*;
public class IteratorTest2{
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("1", "value1");
map.put("2", "value2");
map.put("3", "value3");
//第一种:普遍使用,二次取值
System.out.println("通过Map.keySet遍历key和value:");
for (String key : map.keySet()) {
System.out.println("key= "+ key + " and value= " + map.get(key));
}
//第二种
System.out.println("通过Map.entrySet使用iterator遍历key和value:");
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
//第三种:推荐,尤其是容量大时
System.out.println("通过Map.entrySet遍历key和value");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
//第四种
System.out.println("通过Map.values()遍历所有的value,但不能遍历key");
for (String v : map.values()) {
System.out.println("value= " + v);
}
}
}

运行结果

通过Map.keySet遍历key和value:
key= 1 and value= value1
key= 2 and value= value2
key= 3 and value= value3
通过Map.entrySet使用iterator遍历key和value:
key= 1 and value= value1
key= 2 and value= value2
key= 3 and value= value3
通过Map.entrySet遍历key和value
key= 1 and value= value1
key= 2 and value= value2
key= 3 and value= value3
通过Map.values()遍历所有的value,但不能遍历key
value= value1
value= value2
value= value3

Collection接口

Collection接口声明了管理它所存储的元素的办法

添加、删除

boolean add(E e)将对象添加给集合
boolean remove(Object o)如果集合中有和o匹配的对象,则删除o

查询

int size( )返回集合中的元素个数
boolean ieEmpty( )判断是否为空
boolean contains(Object o)查找是否包含元素o
boolean containsAll(Collection<?>c)查找是否有集合c中的所有元素
Iterator iterator( )返回上一个集合的迭代器,用来访问该集合中的各个元素

组操作

boolean addAll(Collection<?extends E>c)将指定的集合c中的所有元素添加到该集合
void clear()删除集合中所有元素
void removeAll(Collection<?>c)从集合中删除集合c中的所有元素
void retainAll(Collection<?>c)从当前集合中删除指定集合c中不包含的元素

集合与数组间的转换操作

Object[] toArray()把此collect对象转换成数组对象
<T>T[]toArray(T[] a)返回一个内含集合所有元素的数组array

Set接口及实现类

Set接口代表的是不重复的元素的集合。往Set集合里存储对象时,他会调用对象的equal方法与set中已有的元素进行比较。

HashSet实现类

HashSet用散列表存储元素。

当添加元素时,根据元素的哈希值来算出它的存储索引,根据存储索引,存储在散列表中。如果两个对象的存储索引相同,调用equal方法判断,如果两个对象相同,不再存放;如果不同,存在当前位置其它元素的后面。

当使用迭代器迭代set中的元素时,由于它访问的是散列表元,所有并不保证元素存入时的顺序和取出是一样的。

查找元素效率高。

重写equal和hashCode方法。

public class Employee {

	private int id;//编号
	private String name;//姓名
	private double salary;//月薪
	private int age;//年龄
	
	public Employee(){
		
	}
	
	public Employee(int id,String name,double salary,int age){
		this.id=id;
		this.name=name;
		this.salary=salary;
		this.age=age;
	}
	
	public Employee(int id,String name){
		this.id=id;
		this.name=name;
		
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + id;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		long temp;
		temp = Double.doubleToLongBits(salary);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		return result;
	}
	
	

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Employee other = (Employee) obj;
		if (age != other.age)
			return false;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + ", age=" + age + "]";
	}
	

}

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

public class HashSetTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Set<String> set1=new HashSet<String>();//将String类存在散列集
		set1.add("zz");
		set1.add("zzz");
		set1.add("zz");
		System.out.println("set1中的元素个数为:"+set1.size());
		Iterator<String>it=set1.iterator();
		for(;it.hasNext();){//it.hasNext()判断下一个元素之后有值
			System.out.println(it.next()); 
		}//因为String类重写了Object类提供的equal()方法和hashCode()方法,所以不会有重复元素
		
		Set<Employee> set2=new HashSet<Employee>();
		
		Employee e1=new Employee(1,"zs",3500.0,25);
		Employee e2=new Employee(2,"李四",3100.0,24);
		Employee e3=new Employee(3,"王五",5200,65);
		Employee e4=new Employee(4,"奇葩",8900,95);
		Employee e5=new Employee(1,"来了",5200,85);
		System.out.println(e1.equals(e5));
		
		Employee e6=new Employee(1,"zs");
		Employee e7=new Employee(2,"李四");
		Employee e8=new Employee(1,"王五");
		Employee e9=new Employee(2,"奇葩");
		System.out.println(e6.equals(e8));
		
		set2.add(e1);
		set2.add(e2);
		set2.add(e3);
		set2.add(e4);
		set2.add(e5);
//		System.out.println(set2);
		for(Employee e:set2){
			System.out.println(e.toString());
		}
	}

}

运行结果:

set1中的元素个数为:2
zz
zzz
false
false
Employee [id=2, name=李四, salary=3100.0, age=24]
Employee [id=3, name=王五, salary=5200.0, age=65]
Employee [id=1, name=zs, salary=3500.0, age=25]
Employee [id=1, name=来了, salary=5200.0, age=85]
Employee [id=4, name=奇葩, salary=8900.0, age=95]

未能实现“不添加参数id相同的新对象”。

LinkedHashSet实现类

将存储对象放在哈希表中,但会建一个链表记录对象的存放顺序,所以也称链式散列集。不允许重复元素。

import java.util.LinkedHashSet;
import java.util.Set;

public class LinkHashSetDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Set<String> set=new LinkedHashSet<String>();
		set.add("第一个元素");
		set.add("第二个元素");
		set.add("第一个元素");
		set.add("第三个元素");
		
		for(String str:set){
			System.out.println(str);
		}
	}

}
运行结果:
第一个元素
第二个元素
第三个元素

TreeSet

TreeSet是Set系列中用来支持元素自然排序的一个集合,它的内部采用“红黑树”来存储排序后的元素,所以也成为树集。

添加元素自动排序,添加完之后,所有元素的顺序就排好了。

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

public class TreeSetDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Set<String>set1=new TreeSet<String>();
		set1.add("zz");
		set1.add("zzzz");
		set1.add("zzz");
		set1.add("z");
		
		for(String str:set1){
			System.out.println(str);
		}
		
		Set<Integer>set2=new TreeSet<Integer>();
		set2.add(68);
		set2.add(88);
		set2.add(15);
		set2.add(150);
		
		for(int str:set2){
			System.out.println(str);
		}
	}

}

运行结果:

z
zz
zzz
zzzz
15
68
88
150

List接口及实现类

List接口继承了Collection接口,可以保存对象的存放顺序,所以也称序列。该接口在Collection接口的基础上添加了面向位置的操作方法。

void add(int index,E element)在列表的指定位置插入指定值
E get(int index)获取指定位置的元素值
remove(int index)移除指定位置的元素值
set(int index,E element)将指定位置的元素替换为element
int indexOf(Object o)返回该元素第一次出现的索引
int lastIndexOf(Object o)返回该元素最后出现的索引
List<E>subList(int fromIndex,int toIndex)返回列表中指定(fromIndex,toIndex]中的子列表

ArrayList类

ArrayList被称为数组列表,可以动态地增加或减少其容量。

使用索引取出元素的效率高;删除或插入的速度很慢,要移动后面所有元素保持索引的连续。

import java.util.*;
public class ArrayListDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		List<String> list=new ArrayList<String>();
		list.add("zz");
		list.add("cc");
		list.add("vv");
		list.add("zz");
		list.add("bb");
		list.add("mm");
		
//		list.remove(2);
//		for(String str:list){
//		System.out.println(str);
//	}
		String str=list.get(2);
		System.out.println("索引为2的元素:"+str);
		
		list.add(2,"ee");//在指定位置插入
		String str1=list.get(2);
		System.out.println("索引为2的元素:"+str1);
		
		List<String>list1=list.subList(0, 3);
		for(String str2:list1){
			System.out.println(str2);
		}
		
		//三种方法遍历Arraylist
//		for(String str:list){
//			System.out.println(str);
//		}
//		for(int i=0;i<list.size();i++){
//			System.out.println(list.get(i));
//		}
//		for(Iterator<String>it=list.iterator();it.hasNext();){  //在for循环体内构建迭代器
//			System.out.println(it.next());
//		}
	}

}

运行结果:

索引为2的元素:vv
索引为2的元素:ee
zz
cc
ee

LinkedList类

LinkedList类用双向链表结构来保存数据,在双链表中,除了存放数据,还存放两个变量,用来保存上一个节点和下一个节点的引用。

LinkedList插入和删除元素的效率很高,只需更新被删除元素前后的链接即可;但它不适合快速地随机访问某个位置的元素,因为要从头开始查找。

import java.util.*;
public class LinkedListDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		LinkedList<String>list=new LinkedList<String>();
		list.add("zz");
		list.add("cc");
		list.add("vv");
		list.add("zz");
		list.add("bb");
		list.add("mm");
		
		for(String str:list){
			System.out.println(str);
		}
	}

}

Map接口及实现类

映射(Map)用来存放许多键/值对,它是根据唯一的键来找值,用set方法存放映射对的“键”。

添加、删除方法。

V put(K key,V value)将指定的值与键关联,放入该映射中。如果此键存在,新值代替旧值;如果不存在,返回null
V remove(Object key)将指定键的键值对从此映射中移除
void putAll(Map<?extends K,?extends>m)把该映射的所有元素添加到当前映射
void clear()从映射中删除所有映射对

元素查询方法

boolean containsKey(Object key)判断映射中是否含有指定键的映射对
V get(Object key)获取与键对应的值,如果没有,返回null。
boolean cintainsValue(Object value)判断映射中是否有指定值的键值对
int size()返回当前映射中键值对的数量
boolean isEmpty()判断映射是否为空

获取集合视图的方法

Set keySet( )返回映像中所有键的set集
Collection values( )返回映像中所有值的试图Collection集
Set entrySet( )返回Map.Entry对象的视图集

HashMap类

内部对键进行散列排放,根据键去取值,效率很高;不保证映射对的存放顺序。

import java.util.*;
import java.util.Map.Entry;
public class HashMapDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		HashMap<Integer,String>hashSet=new HashMap<Integer,String>();
		hashSet.put(1, "张三");
		hashSet.put(2, "张三");
		hashSet.put(3, "李四");
		hashSet.put(4, "王五");
		
		System.out.println("存放的键值对数量:"+hashSet.size());
		
		System.out.println(hashSet.get("张三"));//找不到键"张三"
		
		HashMap<Integer, String>hashSet1=new HashMap< Integer,  String>();
		hashSet1.put(11, "张三11");
		hashSet1.put(22, "张三22");
		hashSet1.put(33, "李四33");
		hashSet1.put(44, "王五44");
		
		hashSet.putAll(hashSet1);//被添加的映射键值类型必须与原映射一样
		
		Set<Integer> keys=hashSet.keySet();//获取所有的键
		System.out.println(keys);
		System.out.println("遍历键集,根据键取出对应的值");
		for(Iterator<Integer>it=keys.iterator();it.hasNext();){
			Integer key=it.next();
			String value=hashSet.get(key);
			System.out.println("key="+key+",value="+value);
		}
		
		System.out.println("for-each语句遍历");
		for(Integer key:hashSet.keySet()){
			String value=hashSet.get(key);
			System.out.println("key="+key+",value="+value);
		}
		
		System.out.println("获取键值对对象的set集进行遍历");
		for(Entry<Integer,String>entry:hashSet.entrySet()){
			System.out.println("key="+entry.getKey()+",value="+entry.getValue());
		}
		
	}

}
运行结果:
存放的键值对数量:4
null
[1, 33, 2, 3, 4, 22, 11, 44]
遍历键集,根据键取出对应的值
key=1,value=张三
key=33,value=李四33
key=2,value=张三
key=3,value=李四
key=4,value=王五
key=22,value=张三22
key=11,value=张三11
key=44,value=王五44
for-each语句遍历
key=1,value=张三
key=33,value=李四33
key=2,value=张三
key=3,value=李四
key=4,value=王五
key=22,value=张三22
key=11,value=张三11
key=44,value=王五44
获取键值对对象的set集进行遍历
key=1,value=张三
key=33,value=李四33
key=2,value=张三
key=3,value=李四
key=4,value=王五
key=22,value=张三22
key=11,value=张三11
key=44,value=王五44

LinkHashMap类

使用散列表存储键值对、用双链表存储映射对的加入顺序。所以可以实现顺序输出。

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.Map.Entry;

public class LinkedHashMapDemo {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		LinkedHashMap<Integer,String>linkedHashSet=new LinkedHashMap<Integer,String>();
		linkedHashSet.put(1, "张三");
		linkedHashSet.put(2, "张三");
		linkedHashSet.put(3, "李四");
		linkedHashSet.put(4, "王五");
		
		System.out.println("存放的键值对数量:"+linkedHashSet.size());
		
		System.out.println(linkedHashSet.get("张三"));//找不到键"张三"
		
		LinkedHashMap<Integer, String>LinkedHashSet1=new LinkedHashMap< Integer,  String>();
		LinkedHashSet1.put(11, "张三11");
		LinkedHashSet1.put(22, "张三22");
		LinkedHashSet1.put(33, "李四33");
		LinkedHashSet1.put(44, "王五44");
		
		linkedHashSet.putAll(LinkedHashSet1);//被添加的映射键值类型必须与原映射一样
		
		Set<Integer> keys=linkedHashSet.keySet();//获取所有的键
		System.out.println(keys);
		System.out.println("遍历键集,根据键取出对应的值");
		for(Iterator<Integer>it=keys.iterator();it.hasNext();){
			Integer key=it.next();
			String value=linkedHashSet.get(key);
			System.out.println("key="+key+",value="+value);
		}
		
		System.out.println("for-each语句遍历");
		for(Integer key:linkedHashSet.keySet()){
			String value=linkedHashSet.get(key);
			System.out.println("key="+key+",value="+value);
		}
		
		System.out.println("获取键值对对象的set集进行遍历");
		for(Entry<Integer,String>entry:linkedHashSet.entrySet()){
			System.out.println("key="+entry.getKey()+",value="+entry.getValue());
		}
		
	}
}

运行结果:

存放的键值对数量:4
null
[1, 2, 3, 4, 11, 22, 33, 44]
遍历键集,根据键取出对应的值
key=1,value=张三
key=2,value=张三
key=3,value=李四
key=4,value=王五
key=11,value=张三11
key=22,value=张三22
key=33,value=李四33
key=44,value=王五44
for-each语句遍历
key=1,value=张三
key=2,value=张三
key=3,value=李四
key=4,value=王五
key=11,value=张三11
key=22,value=张三22
key=33,value=李四33
key=44,value=王五44
获取键值对对象的set集进行遍历
key=1,value=张三
key=2,value=张三
key=3,value=李四
key=4,value=王五
key=11,value=张三11
key=22,value=张三22
key=33,value=李四33
key=44,value=王五44

遗留的集合类

Vector类

向量(Vector)实现了List接口,与ArrayList类操作方法相同,不同的是提供一个可以返回元素枚举对象的elements()方法,这个枚举接口可以迭代所有元素,还有就是Vector是同步的,ArrayList是不同步的。考虑线程问题可以选择使用。

import java.util.Enumeration;
import java.util.Vector;

public class VectorDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Vector<String>v=new Vector<String>();
		v.add("11");
		v.add("zz");
		v.add("cc");
		
//		for(String str:v){
//			System.out.println(str);
//		}
		//用返回的元素枚举对象e进行遍历
		for(Enumeration<String>e=v.elements();e.hasMoreElements();){
			System.out.println(e.nextElement());
		}
	}

}

运行结果:

11
zz
cc

Stack类

Stack类是Vector的子类,是以后进先出的方式存储元素的堆栈。在Vector的基础上增加了五个方法。

public E push(E item)把元素压入堆栈顶部
public E pop()移除堆栈顶部的对象,并作为此方法的返回值返回该对象
public E peek()查看堆栈顶部的对象,不移除它
public boolean empty()测试堆栈是否为空
public int search(Object o)返回对象在堆栈中的位置,以1为基数

import java.util.Stack;

public class StackTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Stack<Integer>s=new Stack<Integer>();
		//push()把元素放入栈顶
		s.push(111);
		s.push(222);
		s.push(333);
		//pop()移除栈顶元素,并返回该元素值
		System.out.println(s.size());
		int j=s.size();
		for(int i=0;i<j;i++){//直接写i<s.size()只能输出333 222 不知道为啥
			System.out.println(s.pop());
		}
	}

}

运行结果:

3
333
222
111

后进先出的堆栈可以用新增的Deque接口来实现

Hashtable类

Hashtable与HashMap类类似,不同的是Hashtable的各个方法是同步的。如果不需要同步,或者不需要与旧代码兼容,应该使用HashMap类。

Properties类

Properties类是Hashtable类的子类,也叫属性集。它是一个特殊的映射结构,表现在:

1.键和值都是字符串,所以它不是泛型类,不支持泛型操作。

2.属性集的键值可以保存到一个文件,也可以从一个文件中加载。

setProperty(String key,String value)和getProperty(String key)方法存取元素。

import java.io.IOException;
import java.io.InputStream;
/*通过properties类从指定文件中加载属性键值并输出*/
import java.util.*;
public class PropertiesTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//获取文件,并读入输出流
		InputStream is=Thread.currentThread()
				.getContextClassLoader()
				.getResourceAsStream("config.properties");//获取文件,并读入到输入流
		Properties p=new Properties();//创建Properties对象
		try {
			p.load(is);//从流中加载数据
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("username:"+p.getProperty("username"));
		System.out.println("password:"+p.getProperty("password"));
	}

}

config.properties

#key=value     #号为注释行
username=zz
password=123

运行结果:

username:zz
password:123

排序集合

当迭代集合时,集合中的元素按照自动排序后的顺序出现,就需要集合元素实现Comparable接口。

Comparable接口

该接口申明了一个方法  int compareTo(T o),用于元素与指定元素比较;如果大,返回1;如果相等,返回0;如果小,返回-1。

public class Student implements Comparable<Object>{
	private int num;//学号
	private String name;//姓名
	private double score;//成绩

	public Student(){
		
	}
	
	public Student(int num,String name,double score){
		this.num=num;
		this.name=name;
		this.score=score;
	}
	
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getScore() {
		return score;
	}
	public void setScore(double score) {
		this.score = score;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + num;
		long temp;
		temp = Double.doubleToLongBits(score);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (num != other.num)
			return false;
		if (Double.doubleToLongBits(score) != Double.doubleToLongBits(other.score))
			return false;
		return true;
	}
	
	@Override
	public String toString() {
		return "Student [num=" + num + ", name=" + name + ", score=" + score + "]";
	}
//在类中实现Comparable接口的compareTo方法
	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		Student a=(Student) o;//向上转型
		if (this.score>a.score){
			return 1;
		}else if(this.score<a.score){
			return -1;
		}else return 0;
	}

}

    Student a1=new Student(1, "张三", 100);
    Student a2=new Student(1, "李四", 80);
    Student a3=new Student(1, "张三", 80);
    Student a4=new Student(1, "王五", 60);
    Student a5=new Student(1, "小李", 200);

    System.out.println(a1.compareTo(a5));
    System.out.println(a5.compareTo(a1));

运行结果:

-1
1

局限性:一个类只能实现该接口一次,即只能定义一种自然排序的规则。

Comparator接口

Comparator接口的类(排序类)的对象作为参数传递给该排序集合的构造方法,这个排序集合就会按照排序器指定的排序方法排序。

java.lang.Comparator接口只拥有一个方法:

int conpare(T o1,T o2)

定义两个排序器,分别比较学生的成绩和姓名

public class StudentScoreComparator implements Comparator<Student>{


	public int compare(Student a,Student b) {
		if(a.getScore()>b.getScore())
			return 1;
		else if(a.getScore()<b.getScore())
			return -1;
		else return 0;
	}

}

public class StudentNameComparator implements Comparator<Student> {

	@Override
	public int compare(Student a, Student b) {
		return a.getName().compareTo(b.getName());
	}

}

public class StudentTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Student a1=new Student(1, "张三", 100);
		Student a2=new Student(2, "李四", 80);
		Student a3=new Student(3, "张三", 120);
		Student a4=new Student(4, "王五", 60);
		Student a5=new Student(5, "李", 200);
		Student a6=new Student(6, "小红旗", 100);
		
		//存入map表
		HashMap<Integer,Student> h=new HashMap<Integer,Student>();
		h.put(1, a1);
		h.put(2, a2);
		h.put(3, a3);
		h.put(4, a4);
		h.put(5, a5);
		h.put(5, a6);
		System.out.println(a1.compareTo(a5));
		System.out.println(a5.compareTo(a1));
		
//		Set<Integer> key=h.keySet();
//		for(Iterator<Integer>it=key.iterator();it.hasNext();){
//			Integer keys=it.next();
//			Student value=h.get(keys);
//			System.out.println("key="+keys+",value:"+value);
//		}
		
		//存入TreeSet表  会自动按成绩排序
		Set<Student>set=new TreeSet<Student>() ;
		set.add(a1);
		set.add(a2);
		set.add(a3);
		set.add(a4);
		set.add(a5);
		set.add(a6);
		System.out.println("未指定排序器");
		for(Student st:set){
			System.out.println(st);
		}
		
		Set<Student>set1=new TreeSet<Student>(new StudentScoreComparator()) ;
		set1.add(a1);
		set1.add(a2);
		set1.add(a3);
		set1.add(a4);
		set1.add(a5);
		set1.add(a6);
		System.out.println("指定分数排序器(添加元素时,如果分数与以有分数相同,则不添加该对象)");
		for(Student st:set1){
			System.out.println(st);
		}
		
		Set<Student>set2=new TreeSet<Student>(new StudentNameComparator()) ;
		set2.add(a1);
		set2.add(a2);
		set2.add(a3);
		set2.add(a4);
		set2.add(a5);
		set2.add(a6);
		System.out.println("指定姓名排序器(添加元素时,如果名字与以有名字相同,则不添加该对象)");
		for(Student st:set2){
			System.out.println(st);
		}
	}
	

}

运行结果:

-1
1
未指定排序器
Student [num=4, name=王五, score=60.0]
Student [num=2, name=李四, score=80.0]
Student [num=1, name=张三, score=100.0]
Student [num=3, name=张三, score=120.0]
Student [num=5, name=李, score=200.0]
指定分数排序器
Student [num=4, name=王五, score=60.0]
Student [num=2, name=李四, score=80.0]
Student [num=1, name=张三, score=100.0]
Student [num=3, name=张三, score=120.0]
Student [num=5, name=李, score=200.0]
指定姓名排序器
Student [num=6, name=小红旗, score=100.0]
Student [num=1, name=张三, score=100.0]
Student [num=5, name=李, score=200.0]
Student [num=2, name=李四, score=80.0]
Student [num=4, name=王五, score=60.0]

TreeMap类

根据键值排序

Student a1=new Student(1, "张三", 100);
		Student a2=new Student(2, "李四", 80);
		Student a3=new Student(3, "张三", 120);
		Student a4=new Student(4, "王五", 60);
		Student a5=new Student(5, "李", 200);
		Student a6=new Student(6, "小红旗", 100);

//存入treeMap表  会按照键值排序
		TreeMap<Integer,Student>s=new TreeMap<Integer,Student>() ;
		s.put(3,a1);
		s.put(2,a2);
		s.put(1,a3);
		s.put(4,a4);
		s.put(6,a5);
		s.put(5,a6);
		for(Integer key:s.keySet()){
			Student stu=s.get(key);
			System.out.println("key:"+key+",value:"+stu);
		}

运行结果:

key:1,value:Student [num=3, name=张三, score=120.0]
key:2,value:Student [num=2, name=李四, score=80.0]
key:3,value:Student [num=1, name=张三, score=100.0]
key:4,value:Student [num=4, name=王五, score=60.0]
key:5,value:Student [num=6, name=小红旗, score=100.0]
key:6,value:Student [num=5, name=李, score=200.0]

集合工具类Collections

用于集合的常用算法操作,包括极值、排序、混排、查找等。Collections提供的都是类方法,可以直接用类名调用。

极值:

public static <T extends Object&Comparaable<?super>>T max(Collection<? extends T>coll):根据元素的自然顺序,返回给定collection中的最大值。collection中的元素必须都实现Comparaable接口

public static <T extends Object&Comparaable<?super>>T min(Collection<? extends T>coll):根据元素的自然顺序,返回给定collection中的最小值。collection中的元素必须都实现Comparaable接口

public static <T>T  max(Collection<?extends T>coll,Comparator<?super T>comp):根据比较器产生的顺序,返回该collection的最大值

public static <T>T min(Collection<?extends T>coll,Comparator<?super T>comp):根据比较器产生的顺序,返回该collection的最小值

排序:

public static <T extends Comparable><?super T>>void sort(List<T>list):根据元素的自然顺序对集合中的元素进行升序排序,列表中的元素必须实现Comparable接口。

public static<T>void sort(List<T>list,Comparator<?super T>c):根据指定比较器产生的顺序对指定列表进行排序。

混排(打乱元素在集合中的顺序):

public static void shuffle(List<?>list):使用默认随机源对指定列表进行置换。

public static void shuffle(List<?>list,Random rnd):使用指定的随机源对指定列表进行置换。

查找:

public static <T>intbinarySearch(List<?extends Comparable<? super T>>list,T key):使用二分搜索法搜索指定列表,以获得指定对象。(使用该方法前,要对列表进行升序排序)

public static <T>intbinarySearch(List<? extends T>list,T key,Comparator<?super T>c):使用二分搜索法搜索指定列表,以获得指定对象。(使用该方法前,要用指定排序器对列表进行升序排序)

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

public class CollectionsTest {
	public static void main(String[] args) {
		List<String>list=new ArrayList<String>();
		list.add("aaa");
		list.add("fff");
		list.add("bbb");
		list.add("zzz");
		list.add("qqq");
		
		System.out.println(list);
		
		System.out.println("list中的最大值:"+Collections.max(list));
		System.out.println("List中的最小值:"+Collections.min(list));
		
		Collections.sort(list);
		System.out.println("排序后:"+list);
		System.out.println("查找元素\"zzz\"的索引"+Collections.binarySearch(list, "zzz"));
		
		Collections.shuffle(list);
		System.out.println("混排:"+list);
		
		
	}

	
}

同步控制:

HashSet、LinkedHashSet、ArrayList、LinkedList、HashMap、LinkedHashMap、TreeSet和TreeMap都是不同步的。如果多个线程同时操作这些类的实例对象,可能会出现错误。

选择合适的集合:

数据存放顺序无要求   HashSet

数据存放顺序有要求  ArrayList

需要保存数据存放顺序,频繁增删元素  LinkedList

数据需要以“键-值”对的形式存放  HashMap

存放数据需要按自然顺序排序  TreeSet或TreeMap

数据的读写效率:

Hash开头的集合类:元素的读取和修改效率高

Array开头的集合类:元素读取快但修改慢

Linked开头的集合类:元素读取慢但修改快

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值