一、Set接口
//HashSet综合举例 import java.util.*; public class Test{ public static void main(String[] args){ Set<Name> s = new HashSet<Name>(); s.add(new Name("Li","Ming")); s.add(new Name("Sun","Lei")); s.add(new Name("Li","Li")); System.out.println(s.remove(new Name("Li","Ming")));//equals()方法比较相等不能移除,需要重写hashCode() System.out.println(s);//无序的! /* Iterator t = s.iterator(); while(t.hasNext()){ System.out.println(t.next()); t.remove(); } System.out.println(s); */ //交集、并集 Set<Name> s2 = new HashSet<Name>(); s2.add(new Name("Li","M")); s2.add(new Name("Sun","Lei")); s2.add(new Name("Li","Li")); Set<Name> sj = new HashSet<Name>(s); sj.retainAll(s2);//交集 System.out.println(sj); Set<Name> sb = new HashSet<Name>(s); sb.addAll(s2); System.out.println(sb);//并集 } } class Name{ String fn; String ln; public Name(String fn, String ln){ this.fn = fn ; this.ln = ln ; } public boolean equals(Object o){ if(o instanceof Name){ Name n = (Name)o ; return this.fn.equals(n.fn)&&this.ln.equals(n.ln) ; } return false ; } public String toString(){ return fn+" "+ln ; } public int hashCode(){ return fn.hashCode(); } }
Set集合中的对象不按特定的方式排序,不能包含重复对象。Set容器可以与数学中“集合”的概念相对应。
注意:如果改变一个Set中的可变元素,导致重复,将会出现问题。
Set集合由Set接口和Set接口的实现类组成。Set接口实现了Collection接口,因此包含Collection接口的所有方法。J2SDK API中所提供的Set容器类有HashSet类,TreeSet类等。
1、HashSet类实现Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证Set的迭代顺序,特别是它不保证该顺序恒久不变。此类允许使用null元素。
2、TreeSet类不仅实现了Set接口,还实现了java.util.SortedSet接口,因此它在遍历集合时按照自然顺序递增排序,也可以按照指定比较器递增排序,即可以通过比较器对TreeSet类实现的Set集合中的对象进行排序。TreeSet类新增方法如下:
举例1:
import java.util.*; //导入java.util包 public class Test{ public static void main(String args[]){ Set s = new HashSet(); //注意HashSet是无序的,不允许重复的! s.add("hello"); s.add(new Integer(100)); s.add(new Name("f1","l1")); s.add("hello"); s.add(new Name("f1","l1")); System.out.println(s); } } //Name class Name{ private String firstName; private String lastName; public Name(String firstName,String lastName){ this.firstName = firstName; this.lastName = lastName; } public String getFirstName(){ return firstName; } public String toString(){ return firstName + " " + lastName ; } public boolean equals(Object obj) { if(obj instanceof Name){ Name name = (Name) obj; return (firstName.equals(name.firstName))&&(lastName.equals(name.lastName)); } return super.equals(obj); } public int hashCode(){ return firstName.hashCode(); } }
输出:
[hello,100,f1 l1]
注意:Name类应该重写equals()方法。
举例2:
import java.util.*; //导入java.util包 public class Test{ public static void main(String args[]){ Set s1 = new HashSet(); //注意HashSet是无序的! Set s2 = new HashSet(); s1.add("a"); s1.add("b"); s1.add("c"); s2.add("d"); s2.add("a"); s2.add("b"); //Set和List容器类都有Constructor(Collection c)构造方法用以初始化容器类 Set sn = new HashSet(s1); sn.retainAll(s2);//求交集,存入sn Set su = new HashSet(s1); su.addAll(s2);//求并集,存入su。注意会自动去重! System.out.println(sn); System.out.println(su); } }
输出:
[b,a]
[d,b,c,a]
二、List接口
List:
List集合中的元素允许重复,各个元素的顺序就是对象插入的顺序。类似数组,用户可以使用索引(元素在集合中的位置,从0开始)来访问集合中的元素。
List集合由List接口和List接口的实现类组成。List接口实现了Collection接口,因此包含Collection接口的所有方法。此外List接口还提供下面方法:
注意:其中add,remove在Collection接口中有,但是形参不同。Collection接口中的声明如下:
J2SDK所提供的List容器类有ArrayList,LinkedList等。(相当于数组和链表,但是容器类可以自动调节大小)
1、ArrayList类实现了可变数组,允许元素是NULL。 优点:可根据索引位置对集合进行快速访问。缺点:向指定的索引位置插入对象或删除对象的速度较慢。
2、LinkedList类采用链表结构保存对象。 优点:便于向集合中插入和删除对象。缺点:对于随机访问集合中的元素效率较慢。
使用List集合时通常声明为List类型,可通过不同的实现类(ArrayList,LinkedList)实例化集合。例如:
List list = new ArrayList();
List list = new LinkedList();
举例1:List中各种新增方法的使用
import java.util.*; public class Test{ public static void main(String[] args){ List<String> l = new LinkedList<String>(); for(int i=0;i<5;i++){ l.add("a"+i); } System.out.println(l); l.add(3,"a111"); System.out.println(l); l.set(5,"a11111"); System.out.println(l); System.out.println(l.get(3)); System.out.println(l.indexOf("a3")); System.out.println(l.remove(3)); System.out.println(l); System.out.println(l.remove("a3")); System.out.println(l); } }
输出:
[a0, a1, a2, a3, a4]
[a0, a1, a2, a111, a3, a4]
[a0, a1, a2, a111, a3, a11111]
a111
4
a111
[a0, a1, a2, a3, a11111]
true
[a0, a1, a2, a11111]
举例2:
import java.util.*; //导入java.util包 public class Gather{ public static void main(String args[]){ List list = new ArrayList(); System.out.println(list.size());//0 list.add("a"); list.add("b"); list.add("c"); System.out.println(list.size());//3 int i = (int)(Math.random()*(list.size()-1));//随机打印 System.out.println("随机获取数组中元素:"+list.get(i)); list.remove(2); System.out.println(list);//[a,b] for(int j=0;j<list.size();j++){ System.out.println(list.get(j));//a b } } }
三、Collections类
类java.util.Collections提供了一些静态方法实现了基于List容器的一些常用算法。
举例:
import java.util.*; //导入java.util包 public class Test{ public static void main(String args[]){ List l1 = new LinkedList(); for(int i=0;i<=9;i++){ l1.add("a"+i); } System.out.println(l1); Collections.shuffle(l1);//随机排序 System.out.println(l1); Collections.reverse(l1);//逆序 System.out.println(l1); Collections.sort(l1);//排序 System.out.println(l1); System.out.println(Collections.binarySearch(l1,"a5"));//折半查找 } }
输出:
四、Comparable接口
问题:上面的算法根据什么确定容器中对象的“大小”顺序?
所有可以“排序”的类都实现了java.lang.Comparable接口,Comparable接口中只有一个方法:public int compareTo(Object obj);该方法:this==obj时返回0,this>obj时返回正数,this<obj时返回负数。
实现了Comparable接口的类通过实现compareTo方法从而确定该类对象的排序方式。
举例:改写Name类,让其实现Comparable接口,其compareTo方法定义为:(String类已经重写了compareTo方法)
import java.util.*; //导入java.util包 public class Test{ public static void main(String args[]){ List l1 = new LinkedList(); l1.add(new Name("Karl","M")); l1.add(new Name("Steven","Lee")); l1.add(new Name("John","o")); l1.add(new Name("Tom","M")); System.out.println(l1); Collections.sort(l1); System.out.println(l1); } } //Name class Name implements Comparable{ private String firstName; private String lastName; public Name(String firstName,String lastName){ this.firstName = firstName; this.lastName = lastName; } public String getFirstName(){ return firstName; } public String toString(){ return firstName + " " + lastName ; } public boolean equals(Object obj) { if(obj instanceof Name){ Name name = (Name) obj; return (firstName.equals(name.firstName))&&(lastName.equals(name.lastName)); } return super.equals(obj); } public int hashCode(){ return firstName.hashCode(); } public int compareTo(Object o){ Name n = (Name) o; int lastCmp = lastName.compareTo(n.lastName); return (lastCmp != 0 ? lastCmp : firstName.compareTo(n.firstName)); } }
输出:
[Karl M, Steven Lee, John o, Tom M]
[Steven Lee, Karl M, Tom M, John o]