现在的位置: 首页 > 综合 > 正文

java学习脚印:集合(Collection)之算法

2014年02月24日 ⁄ 综合 ⁄ 共 6089字 ⁄ 字号 评论关闭

java学习脚印:集合(Collection)之算法

上接,《java学习脚印:集合(Collection)之实现类》。

集合框架提供了一些诸如排序,查找,打散顺序(Shuffling),逆置,旋转,取最大值,取最小值等基本算法,还可以使用集合框架中的接口实现自己的算法。

这里重点提示一下排序算法和查找算法,其他的算法可参考相关API。

1.排序算法

1.1 java中对象排序的方式

java中的sort排序采用稳定的归并排序算法。

要对一个集合进行排序有两种方法:

1) 实现Comparable接口,进行自然排序。

Comparable该接口声明有方法:

int compareTo(T o),利用该方法对元素进行排序,这称为自然排序(natural ordering) 。对于没有实现Comparable接口的类调用Collections.sort()或者Arrays.sort()方法均会抛出ClassCastException异常


下表给出了实现了Comparable接口的一些类及其自然排序。

(来自:http://docs.oracle.com/javase/tutorial/collections/interfaces/order.html)。

Class

NaturalOrdering

Byte

Signednumerical(有符号数值比较)

Character

Unsignednumerical(无符号数值比较)

Long

Signednumerical

Integer

Signednumerical

Short

Signednumerical

Double

Signednumerical

Float

Signednumerical

BigInteger

Signednumerical

BigDecimal

Signednumerical

Boolean

Boolean.FALSE< Boolean.TRUE

File

System-dependentlexicographic on path name

(依赖于平台的路径字典序)

String

Lexicographic(字典序)

Date

Chronological(年代)

CollationKey

Locale-specificlexicographic

2)构造Comparators比较器,自定义排序规则。

Comparators接口声明有一个比较方法:

public interface Comparator<T> {
    int compare(T o1, T o2);
}

通过像集合类或者sort方法传递一个Comparator即可实现自己所需要的排序。

具体可参见代码案例部分。

1.2 代码实例

这里举出一个首先利用自然排序即按Date排序,然后按照Comparator排序的案例。

注意两种排序方式的使用,以及观察稳定排序的特点。


代码清单1-1 :CollectionsDemo8.java

package com.learningjava;

import java.text.SimpleDateFormat;
import java.util.*;
/**
 * This program illustrate usage of sort method in Collections
 * @author wangdq
 * 2013-11-4
 */
public class CollectionsDemo8 {
	public static void main(String[] args) {
		Employee[] staffs = new Employee[]{
				new Employee("Steve",5500,1986,7,13),
				new Employee("Jack",7000,1986,7,5),
				new Employee("Karl",5000,1985,11,2),
				new Employee("Jason",7000,1980,8,12),
		};
		//before sort
		System.out.println("Original:	"+Arrays.toString(staffs));
		
		//create a backup arraylist and  shuffled it
		ArrayList<Employee> bkList1 = new ArrayList<Employee>(Arrays.asList(staffs));
		Collections.shuffle(bkList1);
		System.out.println("Shuffled:	"+bkList1);
		
		
		//sorted it by natural ordering(compare date)
		ArrayList<Employee> bkList2 = new ArrayList<Employee>(Arrays.asList(staffs));
		Collections.sort(bkList2);
		System.out.println("date order:	"+bkList2);
		
		//sorted it by name via providing a Comparator
		ArrayList<Employee> bkList3 = new ArrayList<Employee>(Arrays.asList(staffs));
		Collections.sort(bkList3,new Comparator<Employee>(){
			@Override
			public int compare(Employee e1, Employee e2) {
				// TODO Auto-generated method stub
				return e1.getName().compareTo(e2.getName());
			}
		});
		System.out.println("name order:	"+bkList3);
		
		//sort based on bkList3
		//thus we get sorted by name and then by salary
		//check if it is a stable sort
		Collections.sort(bkList3,new Comparator<Employee>(){
			@Override
			public int compare(Employee e1, Employee e2) {
				
				return Double.valueOf(e1.getSalary()).
						compareTo(Double.valueOf(e2.getSalary()));
			}
		});
		System.out.println("salary order:	"+bkList3);
		
		
	}
}
/**
 * a class to descript employee
 * origin by the book 《Core Java,Volume I:Fundamentals》
 * @version 1.1 2013-08-07
 */
class Employee implements Comparable<Employee>{
	/**
	 * 
	 * @param name name to set
	 * @param salary salary to set
	 * @param year month day  to create a GregorianCalendar
	 */
	public Employee(String name, double salary, int year,int month,int day) {
		this.name = name;
		this.salary = salary;
		GregorianCalendar calendar = new GregorianCalendar(year,month-1,day);
		this.hireDay = calendar.getTime();
		setId();
	}
	public void raiseSalary(double percent) {
		double raise = salary*percent/100;
		salary += raise;
	}
	public String getName() {
		return name;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	public Date getHireday() {
		return (Date)hireDay.clone();
	}
	public void setHireday(Date hireDay) {
		this.hireDay = hireDay;
	}
	public int getId() {
		return id;
	}
	private void setId() {
		this.id = nextId;
		nextId++;
	}
	@Override
	//sort by hireDay
	public int compareTo(Employee o) {
		// TODO Auto-generated method stub
		return this.hireDay.compareTo(o.getHireday());
	}
	@Override
	public String toString() {
		SimpleDateFormat dateformat =new SimpleDateFormat("yyyy-MM-dd");
		String date = dateformat.format(hireDay);
		return "["+name+","+getSalary()+","+date+"]";
	}
	private String name; 
	private double salary;
	private Date hireDay;
	private int id;
	private static int nextId = 1;
}

运行输出

Original:          [[Steve,5500.0,1986-07-13], [Jack,7000.0,1986-07-05], [Karl,5000.0,1985-11-02], [Jason,7000.0,1980-08-12]]
Shuffled:         [[Jason,7000.0,1980-08-12], [Steve,5500.0,1986-07-13], [Karl,5000.0,1985-11-02], [Jack,7000.0,1986-07-05]]
date order:      [[Jason,7000.0,1980-08-12], [Karl,5000.0,1985-11-02], [Jack,7000.0,1986-07-05], [Steve,5500.0,1986-07-13]]
name order:    [[Jack,7000.0,1986-07-05], [Jason,7000.0,1980-08-12], [Karl,5000.0,1985-11-02], [Steve,5500.0,1986-07-13]]
salary order:    [[Karl,5000.0,1985-11-02], [Steve,5500.0,1986-07-13], [Jack,7000.0,1986-07-05], [Jason,7000.0,1980-08-12]]

这里先按姓名进行了排序,然后按工资进行了排序,工资排序中jack和jason工资相等,因为是稳定排序,所以最后的结果是工资想等者按先前的姓名排序结果排列。

2.查找算法

    java查找排序采用二分查找,要求必须是有序的顺序存贮的列表,否则影响查找结果和查找效率。

查找成功时,返回该元素在列表中的索引;当查找失败时,返回的索引并非无用,它恰好给出了插入该元素的一个参考,查找失败时,元素插入位置为:-pos-1,如下:


int pos = Collections.binarySearch(list, key);
if (pos < 0)
   l.add(-pos-1, key);

下面给出一个实例代码,以加深理解。

代码清单1-2 :CollectionsDemo9.java

package com.learningjava;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

/**
 * This program illustrate usage of search method in Collections
 * @author wangdq
 * 2013-11-4
 */
public class CollectionsDemo9 {
	public static void main(String[] args) {
		Integer[]  ints = new Integer[]{5,13,19,21,37,56,64,75,80,88,92};
		ArrayList<Integer> bkList1 = new ArrayList<>(Arrays.asList(ints));
		
		//before reverse
		System.out.println("original list:	"+Arrays.toString(ints));
		
		//reverse list
		Collections.reverse(bkList1);
		System.out.println("reversed list:	"+bkList1);
		
		//sort the list
		ArrayList<Integer> bkList2 = new ArrayList<>(Arrays.asList(ints));
		Collections.sort(bkList2);
		System.out.println("sorted list:	"+bkList2);
		
		//binary search with included key
		int index = Collections.binarySearch(bkList2, Integer.valueOf(21));
		System.out.println("search 21:	"+index);
		
		//binary search with non-included key
		int Index2 = Collections.binarySearch(bkList2, Integer.valueOf(85));
		System.out.println("search 85:	"+Index2);
		if (Index2 < 0)
			bkList2.add(-Index2-1, Integer.valueOf(85));//insertposition -Index2-1
		System.out.println("after insert:	"+bkList2);
	}
}

运行输出

original list:       [5, 13, 19, 21, 37, 56, 64, 75, 80, 88, 92]
reversed list:    [92, 88, 80, 75, 64, 56, 37, 21, 19, 13, 5]
sorted list:       [5, 13, 19, 21, 37, 56, 64, 75, 80, 88, 92]
search 21:       3
search 85:       -10
after insert:     [5, 13, 19, 21, 37, 56, 64, 75, 80, 85, 88, 92]

【上篇】
【下篇】

抱歉!评论已关闭.