您的位置:首页 > 职场人生

黑马程序员——学习日记之--集合框架知识总结

2015-06-02 09:09 639 查看
——- android培训java培训、期待与您交流! ———-

1—Collection集合



一:集合简述

Collection集合:

它是集合的根接口,不可以直接实现。

Collection 实现了 Iterable 接口,可以用iterator()【迭代器】遍历对象。

Collection集合常用方法:

boolean  add (E  e)                 //添加一个待定类型的元素,添加成功返回 true ,添加失败返回 false 。
boolean  isEmpty ()             //判断集合是否为空,是的话就返回true 。
boolean  contains (Object  o)   //判断集合中是否包含元素 o(注意o的类型)。
boolean  equals (Object  o)     //判断集合与指定对象是否相等,已经覆盖了上帝类中的equals 。
boolean  remove(Object  o)      //移除一个元素,移除成功返回true。

int  size ()            //返回集合中的元素个数。
int  hashCode ()        //返回集合的哈希值。
void  clear ()          //移除Collection中所有元素。
Iterator<> iterator()   //返回集合元素的迭代。


数组和集合同是容器,其不同在于:

  数组长度是固定的。集合长度是可变的。

  数组可以存储基本数据类型,集合只能存储对象,而且可以存储不同类型的对象。

迭代器的概念:

集合的内部都定义了集合元素的取出方式,每种集合的数据结构都不同,迭代器就是抽取了取出方式的共性内容。

泛型:

集合在创建对象时最好明确要存入的元素的类型,这样更安全。

形式如:

ArrayList<String> list=new ArrayList<String>();
//指定集合中只能存储字符串类型。


  这就是泛型限定。

泛型的好处

如果不指定集合的类型,用户在传值时,有可能传入不同类型的元素,而取出时按照统一类型取出,就会出现异常。

所以泛型的出现,就把运行时容易出现的问题ClassCastException 转移到编译时期。

泛型也避免了强转。

泛型类:

当类中要操作的引用数据类型不确定时,就 在类上定义泛型,如:

class Demo<T>
{
private T t;
public T show()
{
return t;
}
}


注意:

静态方法加载时,泛型还未指定,所以不可以访问类上定义的泛型。

定义了泛型之后,创建该类对象时需要指定类型,这样就只可以存入一种类型的元素。

但是创建了对象之后,泛型就被锁定,不可以再传入其他类型,这是泛型类的局限性。

泛型方法

把泛型定义在方法上,可以在同一个对象引用中操作不同类型。

形式:

class Demo
{
public <T> void show(T t) {}    //方法上的泛型放在返回值类型前。
public <T> void print(T t) {}
}


这样定义的泛型就只在本方法中有效,可以一个对象调用多种类型数据。

如果类上的泛型和类中方法上的泛型同名,那么类上的泛型被锁定时,类中方法上的泛型也被锁定。

泛型接口

就是在接口上使用泛型,由实现它的类或者该类的对象指定泛型,如:

interface Inter<T>
{
void show(T t);
}
class Demo implements Inter<String> //接口被实现时指定了泛型,有局限性。
{
public void show(String t) {}
}
class Demo_2<T> implements Inter<T> //接口被实现时不指定类型。
{
public void show(T t) {}
}


泛型限定

当不同类型的泛型调用同一个方法时,该方法不确定是哪一种类型的泛型,所以就用一个占位符表示,

形如:

public void (ArrayList<?> list){}


这样的泛型不可以调用具体类型的方法,因为类型不确定,所以类型中不确定有没有此方法。

问号作为占位符代表类型不确定,但仍然可以是任何类型,如果要缩小范围,就可以写成:

public void (ArrayList<? extends E> list)


这样的泛型限定代表的是上限,意思是只可以接收E类型或者E的子类,

还可以写成:

public void (ArrayList<? super E> list)


这样的泛型代表的是下限,意思是只可以接受E类型或者E的父类。

二:Collection集合框架详解

List

是一个接口,继承自Collection接口。

List 无法实例化,只有实现它的子类可以实例化。

List 可以有重复元素。

List中的元素有角标,可根据元素的角标索引访问元素。

常用方法

boolean  add (E  e)             //往列表最后添加一个待定类型的元素,添加成功返回 true ,添加失败返回 false 。
boolean  isEmpty ()             //判断List是否为空,是的话就返回true 。
boolean  contains (Object  o)   //判断List列表中是否包含指定元素。
boolean  equals (Object  o)     //判断List列表与指定对象是否相等 。
boolean  remove(Object  o)      //移除第一个o元素,移除成功返回true。

void  add(int  index,E  element)//指定位置上插入元素。
void  clear ()                  //移除List列表中所有元素。
int      indeOf (Object  o)     //返回指定元素在列表中第一次出现的位置,如果列表不包含次元素,返回-1.
int      lastIndeOf (Object  o) //返回指定元素在列表中逆向第一次出现的位置,如果列表不包含次元素,返回-1.
int  size ()                    //返回List集合中的元素个数。
int  hashCode ()                //返回List集合的哈希值。
E    get (int  index)           //返回列表中指定位置上的元素。
E    remove (int  index)        //移除指定位置上的元素,返回被移除元素,可能抛角标越界异常。
E    set(int  index,E  element) //用指定元素替代指定角标上的元素,返回被替换元素,要抛异常。

boolean  removeAll(Collection<?>  c)    //移除指定List中和c重复的所有元素。
boolean  retainAll(Collection<?>  c)    //保留指定List中和c重复的所有元素。
List<E>  subList (int from,int to)      //截取一个短的List集合,从from到to,包含头不包含尾。
Object  [] toArray()                    //返回按适当顺序排列的数组。
T  [] toArray (T []  a)                 //返回指定类型的数组。
Iterator<E> iterator()                  //按适当顺序在列表的元素上进行迭代的迭代器。Iterator只能对元素判断,修改,取出。
ListIterator<E> listIterator            //返回列表元素的列表迭代器。功能比Iterator多。


ArrayList

它是数组集合。

ArrayList实现了List接口,它可以实例化。

构造时,

  ArrayList()   默认构造一个初始容量10的列表,

  ArrayList(int n)构造一个初始容量为n的列表。

ArrayList**常用方法**基本与List相同。

举例: ArrayList 常见方法使用示例

import java.util.*;
class Demo {
public static void main(String [] args) {
ArrayList<String> arrlist=new ArrayList<String>();
arrlist.add("java01");  //添加元素
arrlist.add("java02");
arrlist.add("java03");
System.out.println(arrlist);  //直接打印集合。[java01, java02,java03]
System.out.println(arrlist.get(1)); //获取角标1上的元素。
int L=arrlist.size();         //L指arrlist的长度,3.

System.out.println(arrlist.remove(1));   //删除1角标上的元素,并返回此元素。打印java02 。
System.out.println(arrlist.indexOf("java02")); //获取对象角标。
System.out.println(arrlist.remove("java01"));    //删除指定元素。返回是否删除成功,true。
System.out.println(arrlist.contains("java01"));//已经移除,不包含,返回false。
System.out.println(arrlist);         //元素只剩下:[java03]
arrlist.add(0,"JAVA");             //指定位置添加元素
System.out.println(arrlist);     //打印数组:[JAVA,java03]
//由此可见移除元素时,后面元素的角标会改变。

arrlist.clear();                    //清空元素
System.out.println(arrlist.size());  //元素个数0.
System.out.println(arrlist.isEmpty());  //ArrayList为空,返回true。
}
}


迭代器的用法:

举例: ArrayList 用迭代器取出元素

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


或者:

for (Iterator it=arrlist.iterator();it.hasNext(); )
{
System.out.println(it.next());
}


注意:写成for循环可以不用在外部定义迭代器,节省内存。而且代码更简洁。

ArrayList 特有的列表迭代器–ListIterator

  Iterator 只能对元素判断,取出,删除, ListIterator 更可以对元素添加和修改。

ArrayList<String> al=new ArrayList<String>();
al.add("01");
al.add("02");
al.add("03");
for (ListIterator<String> lit=al.listIterator();lit.hasNext(); )
{
String s=lit.next();
if (s.equals("02"))
{
lit.set("JAVA2");
lit.add("java02");  //这两句不可以换位
}
}


注意: ListIterator 只能先修改再添加,不可以先添加再去修改。

因为如果先添加元素,元素后的角标都会变,再去修改就出现状态异常:IllegalStateException

练习1: ArrayList集合 去除重复元素方法。

  定义好ArrayList后,新建一个临时数组集合,用于存储集合元素。

然后迭代ArrayList的元素以判断是否包含的形式选择添加进临时数组集合,然后再迭代取出。

import java.util.*;
class Demo {
public static void main(String [] args) {
ArrayList<String> al=new ArrayList<String>();
al.add("01");
al.add("02");
al.add("03");
al.add("03");
al = noRepeat(al);
System.out.println(al);
}
public static ArrayList<String> noRepeat(ArrayList<String> al) {
ArrayList<String> arrlist = new ArrayList<String>();
for (Iterator<String> it=al.iterator();it.hasNext(); ) {
String s=it.next();
if (!(arrlist.contains(s)))
arrlist.add(s);
}
return arrlist;
}
}


练习2:集合中存储自定义对象的去重复方法:。

  集合中如果添加的是自定义的对象,集合中存储的是对象的引用,那么所有对象都不会相同。

所以就要在对象类中重写equals方法以判断元素的内容是否相同,然后迭代取出。

import java.util.*;
class Person {
private String name;
private int  age;
Person(String name,int age) {
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean equals(Object oo) {
if (!(oo instanceof Person))
return false;
Person p = (Person)oo;
return this.name==p.name && this.age==p.age;
}
}

class Demo {
public static void main(String [] args) {
ArrayList<Person> al=new ArrayList<Person>();
al.add(new Person("01",12));
al.add(new Person("02",13));
al.add(new Person("01",12));
al.add(new Person("01",13));
al=noRepeat(al);
for (Iterator<Person> it=al.iterator();it.hasNext(); ) {
Person p=it.next();
System.out.println(p.getName()+" + "+p.getAge());
}
}
public static ArrayList<Person> noRepeat(ArrayList<Person> al) {
ArrayList<Person> arrlist = new ArrayList<Person>();
for (Iterator<Person> it=al.iterator();it.hasNext(); ) {
Person p=it.next();
if (!arrlist.contains(p))
arrlist.add(p);
}
return arrlist;
}
}


注意:

(1)集合中存储的其实是对象的引用地址值。

(2)元素取出时,要调用对象的方法取出元素值。

(3)从太难受方法调用了equal是方法,所以对于对象引用的比较,应该重写equals方法。

(4)注意equals方法比较的是Object类型,所以有向上转型和向下转型。

LinkedList

–链表集合。

  LinkedList集合的特点是,集合中的元素没有角标,每个元素会和它前一个元素形成关系,这样就组成了一个链表。

当要对LinkedList中的元素查询的时候就要一个一个判断,速度慢。

但是当要增删的时候就比较快,因为不需要改动后面所有元素的角标了,只需要改变指定元素周围的关系就可以。

LinkedList 常用方法和List基本相同,

LinkedList 特有的方法:

void  addFirst (E  e)       //将元素插入到开头。
void  addLast (E  e)        //将元素插入到末尾。

//这几个方法如果列表为空会抛NoSuchElementException异常。
E  getFirst ()      //获取第一个元素。
E  getLast ()       //获取最后一个元素。
E  removeFirst ()   //移除并返回第一个元素。
E  removeLast ()    //移除并返回最后一个元素。


从JDK1.6开始,出现了新方法,功能和以上一样,但是都不会再抛NoSuchElementException异常。

void  offer (E  e)
void  offerFirst (E  e)
void  offerLast (E  e)
E  peek ()
E  peekFirst ()
E  peekLast ()
E  poll ()
E  poolFirst ()
E  pollLast ()


举例: LinkedList 模拟堆栈的先进后出数据结构和队列的先进先出数据结构。

import java.util.*;
class Zhan {
private LinkedList<Object> ll=new LinkedList<Object>();
public void myAdd(Object oo) {
ll.offer(oo);           //从末尾添加元素
}
public Object myGet() {
return ll.pollLast();   //从末尾获取元素并移除
}
public boolean isNull() {
return ll.isEmpty();    //判断集合是否为空
}
}
class Dui {
private LinkedList<Object> ll=new LinkedList<Object>();
public void myAdd(Object oo) {
ll.offer(oo);           //从末尾添加元素
}
public Object myGet() {
return ll.pollFirst();  //从开头获取元素并移除
}
public boolean isNull() {
return ll.isEmpty();    //判断集合是否为空
}
}
class Demo {
public static void main(String [] args) {
Zhan z=new Zhan();
z.myAdd("z1");
z.myAdd("z2");
z.myAdd("z3");
while (!z.isNull())
System.out.println(z.myGet());

Dui d=new Dui();
d.myAdd("d1");
d.myAdd("d2");
d.myAdd("d3");
while (!d.isNull())
System.out.println(d.myGet());
}
}


注意: LinkedList 如果泛型写成占位符形式
LinkedList<?>
那么就不能往集合中添加Object元素。

Set

 Set集合不包含重复元素,包括null值也不可重复。

元素是无序的。

Set 继承自 Collection , 它也是一个接口,不可以直接实例化。

Set集合的常用方法和Collection基本相同。

HashSet

HashSet 底层数据结构是哈希表数据结构。

HashSet 是Set集合的一个子类,允许使用null元素。

HashSet 集合存元素时,不可以存相同的元素,包括null元素都不可以重复。

数据存储时不是按照元素顺序排列,而是内存中对象的哈希值顺序,元素取出时也是按照哈希表的顺序取出,所以是无序的。

HashSet 构造方法:

HashSet()               //构造一个默认初始容量16的Set集合
HashSet(int len)        //构造一个指定初始容量的Set集合
HashSet(Collection c)   //构造一个包含指定集合的Set集合


Set 常用方法:

int size()                  //返回集合长度
void clear()                //移除集合中所有元素
boolean add(E e)            //对集合添加一个元素并返回是否添加成功
boolean isEmpty()           //判断集合是否为空
boolean remove(Object oo)   //移除指定元素并返回是否移除成功
boolean contains(Object oo) //返回集合中是否包含指定元素
Iterator<E> iterator()      //返回对此Set集合中元素迭代的迭代器


Set集合存入自定义对象时,实际存入的也是对象的引用。这时候系统会先判断对象的引用是否相同。

所以就要覆盖对象的hashCode()方法,让对象的引用都相同。引用相同时,系统还会调用equals()方法再判断一次存入的对象的内容是否相同。

所以也要重写equals方法。

举例: Set 集合存储自定义对象。

import java.util.*;
class Person {
private String name;
private int age;
Person (String name,int age) {
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean equals(Object oo) {
//已经限定集合类型为Person,所以不用判断类型
//  if (!(oo instanceof Person))
//      return false;
Person p=(Person)oo;
return this.name == p.name && this.age==p.age;
}
public int hashCode() {
return 123*45;
}
}
class Demo {
public static void main(String [] args) {
HashSet<Person> hs=new HashSet<Person>();
hs.add(new Person("s1",12));
hs.add(new Person("s2",13));
hs.add(new Person("s1",12));
hs.add(new Person("s4",13));
for (Iterator<Person> it=hs.iterator(); it.hasNext(); ) {
Person p=(Person)it.next();
System.out.println(p.getName()+"    "+p.getAge());
}
}
}


注意:

(1)Set集合存入元素时,会先给对象分配哈希值,重写hashCode方法是为了让各个对象的哈希值相同;如果哈希值相同,就比较元素内容。

(2)重写equals方法是为了可以比较对象方法返回的内容是否相同。

(3)判断元素是否在集合中存在,先调用hashCode方法判断元素的哈希值是否相等,再调用equals方法判断元素内容是否相等。

(4)移除元素也是先判断哈希值,再判断元素内容。

(5)Set集合和List集合判断元素是否相同差别在于List不判断哈希值。

TreeSet

特点: TreeSet 底层数据结构是二叉树结构。

TreeSet 集合中存入的元素必须具备比较性。

TreeSet 可以对Set集合中的元素进行自然排序。

TreeSet常用方法和Set基本相同,

TreeSet特有方法:

(1)构造方法:

TreeSet(Comparator<? super E> c)//此比较器可以接收TreeSet集合接受的类型或者它的父类


(2)一般方法:

E first()       //返回集合中第一个元素
E last()        //返回集合中最后一个元素
E pollFirst()   //获取并移除第一个元素
E pollLast()    //获取并移除最后一个元素
E ceiling(E e)  //返回集合中大于等于指定元素的最小元素,不存在则放回null
E floor(E e)    //返回集合中小于等于指定元素的最大元素,不存在则返回null

Comparator<? super E> comparator()  //返回对集合中元素排序的比较器,如果是自然排序就返回null
Iterator<E> descendingIterator()    //返回集合中降序迭代的迭代器


TreeSet集合元素手动排序的第一种方式:让元素自身具备比较性。

  需要实现 Comparable接口,并且覆盖接口中的compareTo方法。

举例:

import java.util.*;
class Person implements Comparable<Person> {
private String name;
private int age;
Person (String name,int age) {
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int compareTo(Person p)
{
if (this.age<p.age)
return -1;
if (this.age>p.age)
return 1;
return this.name.compareTo(p.name);
}
}
class Demo {
public static void main(String [] args) {
TreeSet<Person> ts=new TreeSet<Person>();
ts.add(new Person("s1",12));
ts.add(new Person("s2",13));
ts.add(new Person("s1",12));
ts.add(new Person("s4",13));
for (Iterator<Person> it=ts.iterator(); it.hasNext(); ) {
Person p=(Person)it.next();
System.out.println(p.getName()+"++"+p.getAge());
}
}
}


注意: Comparable接口的compareTo方法参数类型是跟随Comparable的泛型的。

TreeSet 集合手动排序的第二种方式:让集合自身具备比较性。

  当元素自身不具备比较性或者不是所需的比较性时,就要让集合自身具备比较性。

先定义一个比较器,然后在集合初始化时,将比较其对象作为参数传递给TreeSet集合的构造函数。

接口 Comparator 是用于强制对对象排序的比较器。

它有两个抽象方法:

equals(Object oo)
compare(Object o1,Object o2)
//注意不是compareTo,而是compare。


定义比较器的示例

class Com implements Comparator<Person>
{
public int compare(Person p1,Person p2)
{
int n = p1.getName().compareTo(p2.getName());
if (n==0)
return new Integer(p1.getAge()).compareTo(new Integer(p2.getAge()));
return n;
}
}


注意:

这里不重写equals方法,是因为类继承Object,已经有equals方法。

compare方法参数类型是跟随Comparator接口的泛型类型的。

定义了比较器之后,就可以通过TreeSet的构造函数:
TreeSet(Comparator<? super E> c);
让集合自身具备比较性,然后通过传递参数的形式,在创建TreeSet对象时,添加参数:
TreeSet<E> ts=new TreeSet<E>(new MyComparator());


就可以对TreeSet集合中的元素进行排序。

注意:

当两种排序方法都存在时,比较器接口是对外提供的功能扩展,一般以比较器为主。

举例: TreeSet 排序练习:按字符串长度排序。

import java.util.*;
class Demo
{
public static void main(String [] args)
{
TreeSet<String> ts=new TreeSet<String>(new MyCom());
ts.add("aabsd");
ts.add("aaasd");
ts.add("vcx");
ts.add("q");
for (Iterator<String> it=ts.iterator();it.hasNext(); )
{
System.out.println(it.next());
}
}
}
class MyCom implements Comparator<String>
{
public int compare(String s1,String s2)
{
int n = new Integer(s1.length()).compareTo(new Integer(s2.length()));
if (n==0)
return s1.compareTo(s2);
return n;
}
}


注意:

String 类有compareTo方法,可以比较字符串并返回负数,零,正数。

定义比较器比较时,往往需要比较两个内容,一个是两对象要比较的条件是否相等,一个是两对象是否是同一个。

此例还可以写成匿名内部类的形式。

2—Map 集合



一:Map集合简述

Map集合:

用于存储键值对,形成一个映射,Map集合反应的是键与值的映射关系,而且关系唯一。

常用方法:

int size()              //返回映射中的键值映射关系数。
void clear()            //从映射中移除所有映射关系。
int hashCode()          //返回此映射的哈希码值。
boolean isEmpty()       //判断映射是否为空。
V get(Object key)       //返回key对应的value值,如果不存在返回null。
V put(K key,V value)    //添加一个映射关系,返回被覆盖的value值。
V remove(Object key)    //如果存在键为key的映射关系,则将其移除,不存在返回null。

boolean equals(Object oo)           //比较指定对象与此映射是否相等。
boolean containsKey(Object key)     //返回映射是否包含指定key值。
boolean containsValue(Object value) //返回映射是否包含指定value值。

Set<K> keySet()                 //返回映射中包含的键的Set视图。
Collection<V> values()          //返回映射中包含的值的Collection视图。
Set<Map.Entry<K,V>> entrySet()  //返回映射中包含的映射关系的Set视图。


举例: Map常用方法用法示例。

import java.util.*;
class Demo
{
public static void main(String [] args)
{
Map<String,String> map=new HashMap<String,String>();
map.put("01","zhang01");
map.put("02","zhang02");
map.put(null,"zhang03");    //null可以作为键存在,但只能有一个null键。

System.out.println(map.containsKey("02"));//判断是否包含"02"键。
System.out.println(map.get("02"));      //返回"02"键对应的值并打印,不存在此键值就返回null。
System.out.println(map.remove("02"));   //移除并返回"02"键的值,不存在此键就返回null。
System.out.println(map);                //直接打印Map集合:{01=zhang01, 03=zhang03}

System.out.println(map.values());       //打印Collection集合:[zhang01, zhang03]

System.out.println(map.put("01","001"));//映射中存在同名键,所以会覆盖"01"键对应的值,并返回被覆盖的value值。
}
}


Map 集合取出

Map集合元素取出的第一种方式keySet方法。

keySet 取出此映射中所有的键,存入一个Set集合。

因为Set具备迭代器,所以可以迭代取出所有的键,然后get方法获取键对应的值。

Map 集合的取出原理:将Map集合转成Set集合,再通过迭代器取出。Map集合本身不需要迭代器。

举例: keySet方法取出映射中的键与值。

import java.util.*;
class Demo {
public static void main(String [] args) {
Map<String,String> map=new HashMap<String,String>();
map.put("01","zhang01");
map.put("02","zhang02");
map.put("03","zhang03");

Set<String> set=map.keySet();   //返回由Map集合中所有键值组成的Set集合。
for (Iterator<String> it=set.iterator();it.hasNext(); ) {
String key=it.next();
System.out.println("key:"+key+" + value:"+map.get(key));
}
}
}


Map 集合取出的第二种方式entrySet方法。

entrySet 返回的是一个键值映射关系Set视图,这种关系的数据类型是 Map.Entry。

Map.Entry 是Map接口中的一个静态内部接口。

常见方法:

boolean equals(Object oo)   //比较两对象是否相等。
int hashCode()              //返回对象哈希值
K getKey()                  //获取对象的键。
V getValue()                //获取对象的值。
V setValue(V value)         //修改对象的值。


举例: entrySet方法取出映射中的键与值。

import java.util.*;
class Demo {
public static void main(String [] args) {
Map<String,String> map=new HashMap<String,String>();
map.put("01","zhang01");
map.put("02","zhang02");
map.put("03","zhang03");

Set<Map.Entry<String,String>> set=map.entrySet();
for (Iterator<Map.Entry<String,String>> it=set.iterator();it.hasNext(); ) {
Map.Entry<String,String> entry=it.next();
String key=entry.getKey();
String value=entry.getValue();
System.out.println(key+":"+value);
}
}
}


练习:

学生具有属性:姓名,年龄;同时具有归属地。

存入几个学生对象,以属性作为键,归属地作为值,并可以按学生年龄降序。

import java.util.*;
class Student implements Comparable<Student> {  //实现比较器,用于排序。
private String name;
private int age;
Student(String name,int age) {
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int hashCode() {
return name.hashCode()+age*45;
}
public boolean equals(Object oo) {
if (!(oo instanceof Student))
throw new ClassCastException("!类型不匹配!");
Student s=(Student)oo;
return this.name.equals(s.name) && this.age==s.age;
}
public int compareTo(Student s) {
int num=new Integer(s.age).compareTo(new Integer(this.age));
if (num==0)
return this.name.compareTo(s.name);
return num;
}
}
class Demo {
public static void main(String [] args) {
TreeMap<Student,String> tm=new TreeMap<Student,String>();
tm.put(new Student("L1",21),"北京");
tm.put(new Student("L2",20),"南京");
tm.put(new Student("L2",20),"天津");
tm.put(new Student("L3",25),"上海");
//keySet方法取出Map集合元素。
Set<Student> keySet=tm.keySet();
for (Iterator<Student> it=keySet.iterator();it.hasNext(); ) {
Student s=it.next();
System.out.println(s.getName()+"+"+s.getAge()+"<->"+tm.get(s));
}
//entrySet方法取出Map集合元素。
Set<Map.Entry<Student,String>> entrySet=tm.entrySet();
for (Iterator<Map.Entry<Student,String>> it=entrySet.iterator();it.hasNext(); ) {
Map.Entry<Student,String> me=it.next();
Student s=me.getKey();
String str=me.getValue();
System.out.println(s.getName()+" : "+s.getAge()+"<->"+str);
}
}
}


注意:

Map集合必须存键值对象两个元素,可根据对象属性特点选择哪一个属性作为键。

Map集合存入重复元素时,后存入的元素会覆盖之前的元素。

TreeMap 也可以传入比较器用于对元素排序。此例如果要以姓名升序排列,可以自定义比较器。

练习2:

获取字符串中字幕出现次数。形式:a(2) b(4) c(1) …

import java.util.*;
class Demo {
public static void main(String [] args) {
String s="hcgngvsgjsbcgscbgsibscgjvjbjkbxkcjsbkjv";
//可根据需要将字符串判断一次,确保字符串全是字母,没有数字或其他字符。

printTime(s);
}
public static void printTime(String s) {
char [] ch=s.toCharArray();
TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();
for (int x=0;x<ch.length;x++) {
char c=ch[x];
int i=0;
if (tm.containsKey(c))
i=tm.get(c);
tm.put(c,++i);
}
Set<Map.Entry<Character,Integer>> entrySet=tm.entrySet();
for (Iterator<Map.Entry<Character,Integer>> it=entrySet.iterator();it.hasNext(); ) {
Map.Entry<Character,Integer> me=it.next();
char c=me.getKey();
int i=me.getValue();
System.out.print(c+"("+i+") ");
}
}
}


注意:

  泛型中接收的都是引用数据类型,不可以接受基础数据类型。

练习3: Map集合的嵌套循环,打印学校中所有班级的学生信息。

import java.util.*;
class Demo {
public static void main(String [] args) {
//创建一个基础班
HashMap<String,String> jichu=new HashMap<String,String>();
jichu.put("01","zhang");
jichu.put("02","wang");
//创建一个就业班
HashMap<String,String> jiuye=new HashMap<String,String>();
jiuye.put("001","zhao");
jiuye.put("002","zhou");
//创建一个学校
HashMap<String,HashMap<String,String>> school=
new HashMap<String,HashMap<String,String>>();
school.put("基础班",jichu);
school.put("就业班",jiuye);

for (Iterator<String> it=school.keySet().iterator();it.hasNext(); ) {
String roomName=it.next();
System.out.println(roomName);
HashMap<String,String> room=school.get(roomName);

//取出班级里的学生
for (Iterator<String> it2=room.keySet().iterator();it2.hasNext(); ) {
String id=it2.next();
String name=room.get(id);
System.out.println(id+"+"+name);
}
}
}
}


注意:一般情况下,使用keySet更简便一些。它不涉及Map.Entry接口。

3—集合工具

一:Collections

Collections 是用于对集合进行操作的工具类。

该类没有构造函数,不需要创建对象。该类中所有方法都是静态的。

Collections 中的泛型比较复杂, 这里通过练习的形式只简单介绍方法的用法。

Collections 的简单方法。

import java.util.*;
class Demo {
public static void main(String [] args) {
List<String> list=new ArrayList<String>();
list.add("sss");
list.add("aa");
list.add("k");
list.add("dddd");
Collections.sort(list);          //对集合自然排序,没有返回值。
System.out.println(list);
Collections.sort(list,new Com());//对集合比较器排序,没有返回值。
System.out.println(list);

System.out.println(Collections.max(list));   //打印集合自然排序后的最大值。
System.out.println(Collections.min(list,new Com()));//打印集合比较器排序后的最小值。
System.out.println(Collections.binarySearch(list,"aa"));//打印二分查找元素的索引。

Collections.fill(list,"A"); //将集合中所有元素替换成"A"。
System.out.println(list);
Collections.reverse(list);  //反转集合元素。
System.out.println(list);
Collections.replaceAll(list,"A","B");//将集合中所有"A"替换成“B”。
System.out.println(list);
Collections.swap(list,1,2); //置换两角标位的元素。
System.out.println(list);
Collections.shuffle(list);  //随机排列集合元素。
System.out.println(list);
}
}
class Com implements Comparator<String> {
public int compare(String s1,String s2) {
int num=new Integer(s1.length()).compareTo(new Integer(s2.length()));
if (num==0)
return s1.compareTo(s2);
return num;
}
}


注意:

 (1) ArrayList 不像TreeSet、TreeMap那样,它不可以传比较器作为参数。

 (2) 如果是自然排序,就直接
Collections.sort(list)
,如果是自定义排序,就需要加比较其对象参数:
Collections.sort(list,new Com())


 (3)取最值时,元素在max方法中会重新排序,然后调用max方法会取出最右侧的值,调用min方法会取出最左侧的值。

Collections 的reverseOrder方法:

对于需要传入比较器的String类型集合对象,如TreeSet、TreeMap,

如果传入比较器Com用于对字符串按长度排序,

可以写成:
TreeSet<String> ts=new TreeSet<String>(new Com());


如果想要将排序改成长度降序,可以写成:

TreeSet<String> ts=new TreeSet<String>(Collections.reverseOrder(new Com()));


reverseOrder方法用于将顺序反转。

Collections 的synchronizedCollection方法:

集合中的很多方法都是线程不安全的,在多线程时容易出现安全问题。

synchronizedCollection方法可以接受一个不安全的集合线程,返回一个安全的集合线程。

和它类似的还有 synchronizedList方法,synchronizedMap方法,synchronizedSet方法。

二:Arrays 类

Arrays类中主要是对数组的操作方法,而且方法都是静态的。

例如,数组二分查找:binarySearch方法,数组排序:sort方法,数组转字符串:toString方法等。

Arrays 中数组转集合的方法:asList方法。

import java.util.*;
class Demo
{
public static void main(String [] args)
{
String [] arr={"aa","cc","ff","acf"};
System.out.println(Arrays.toString(arr));
//将数组打印,形式如: [aa, cc, ff, acf]

List<String> list=Arrays.asList(arr);
System.out.println(list);
}
}


注意:

 (1)Arrays 的asList方法将数组转成集合后,因为数组的长度是固定的,所以不支持使用集合的增删方法。

 (2)如果数组中的元素都是对象,数组转集合时,数组元素就可以直接转成集合中的元素。

  如果数组中的元素都是基本数据类型,数组转集合时,会将数组作为集合元素存入集合。

  所以数组转集合时,最好不是基本数据类型的数组。

 (3)数组编辑和就可以用集合中的一些方法操作数组。

集合转成数组:toArray(T [] t)方法。

Collection接口中提供了toArray方法,可以将集合转成数组。

toArray方法如果不带参数,就返回Object类型的数组,

如果以一个数组为参数,就以参数类型为返回的数组类型。

对于ArrayList集合: [“aa”,”cc”,”ff”,”acf”]

可以返回一个String类型数组:
String [] arr=list.toArray(new String [list.size()]);


这个数组包含集合中的元素。

注意:

 (1)toArray方法中传入一个新建的数组作为参数,这个数组的长度如果比集合长度小,

  该方法内部会自动新建一个长度刚好的数组。如果定义的数组长度比集合长度大,

  就不会新建数组,而是顺序存入元素,没有存值的角标位值为默认值null。

 (2)集合变数组是为了限制对元素的增删操作。

三:其他常见方法的应用

高级for循环:

迭代器可以简写成高级for循环的形式。

来看一个迭代器,

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


此迭代器可以简写成:

for (String s : list)
{
System.out.println(s);
}


这就是高级for循环的应用。

高级for循环底层就是用的迭代器原理。

可变参数:

方法中的参数数量可以变化。

如:

public static void show(int ... arr)
{
System.out.println(arr.length);
}
public static void main(String [] args)
{
show(3);        //打印1
show(4,5,6,7,8);//打印5
}


此例中是往show方法中传入一个数组,并且自动将传入的int整数封装成一个数组。

相当于

int [] arr={4,5,6,7,8};
show(arr);


注意:在使用可变参数时,参数列表中可变参数要放在最后面,否则系统分不清哪些参数要封装进可变参数。

静态导入:

导包后,调用方法可以不写类名调用,静态导包后,可以不写名字,直接用方法。

形式:

import static java.util.Arrays.*;
class Demo
{
public static void main(String [] args)
{
int [] arr={4,2,3};
sort(arr);      //Arrays.sort(arr);的简写
System.out.println(Arrays.toString(arr));
}
}


注意:

(1) Arrays 类中有toString()方法,Object类中也有toString()方法,

  这时,就要表明是 Object.toString() 还是 Arrays.toString()。

(2) import 后加static时,导入的是这个类的所有静态成员。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: