java笔记之集合

              Java学习笔记之集合框架

1、集合类的特点:

集合只用于存储对象,集合长度是可变的,集合可用于存储不同长度的对象。

2、集合和数组都是容器,他们有什么不同?

集合只用于存储对象,其长度是可变的;数组也可以存储对象,用于存储基 

数据类型,但其长度不可变

3、Collection由两个常见的子接口List(元素有序,元素可以重复,该集合体有索引)和Set(元素无序,元素不可以重复)组成,List常见的子类有ArrayList, LinkedListVectorSet常见的子类有HashSetTreeSet

出现不同容器的原因是:容器的数据结构不同,即对数据的存储方式不同

4、迭代器 Iterator 一个接口,它对外提供了一个方法iterator();来取出集合中的对象。比喻:电玩城中投游戏币夹子夹玩具的例子,盛玩具和夹子的大容器就相当于集合,夹子就相当于迭代器就是取出方式,定义在容器内部,是内部类,可以直接访问集合内容的元素,玩具就相当于集合中的元素,操纵杆就相当于iterator()方法,调用iterator()方法,取出集合中的元素。

5Iterator接口有三个方法,hasNext();如果集合中有元素则返回true,否则返回falsenext()方法是取出集合中的一个元素,remove()方法移除迭代器返回的最后一个元素

代码:ArrayList a1=new ArrayList();

//对集合a1添加元素

a1.add("java01");

a1.add("java02");

a1.add("java03");

a1.add("java04");

//获取迭代器,用于取出集合中的元素

Iterator it=a1.iterator();//查阅api可知iterator的返回类型是Iterator

while(it.hasNext())

{

System.out.println(it.next());

6. List:特有方法,只要可以在操作角标的方法都是该体系特有的方法,这里只列举它特有的方法

 *增:add(index,element); addAll(index,Collection);

 *删:remove(index);

 *改:set(index,element)

 *查:get(index);  subList(from,to);  listIterator(); 

代码://获取全部元素,方法一

for(int i=0;i<a1.size();i++)

{

System.out.println(i+"角标处的元素:"+a1.get(i));

}

//获取全部元素,通过迭代器

Iterator lit=a1.iterator();

while(lit.hasNext())

{

System.out.println(lit.next());

}

7List集合特有的迭代器,ListIteratorIterator的子类

在迭代时,不可以通过集合对象的方法操作集合中的元素,会发生异常。所以在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,删除,取出操作。如果想要添加,修改等,就需要使用其子接口ListIterator,该接口只能通过List集合的listIterator方法获取。

代码://在迭代过程中准备添加和修改

ListIterator li=a1.listIterator();

while(li.hasNext())

{

Object obj=li.next();

//如果遇到java02就在它后面添加java05

if(obj.equals("java02"))

li.add("java05");

}

System.out.println(a1);

//可以逆向遍历取出,执行到上一行代码,,指针已经落在最后一个元素的后边

while(li.hasPrevious())

{

System.out.println(li.previous());

}

8、List常见的子类:ArryList:底层的数据结构是数组结构,查询速度快,增删较慢;LinkedList:其数据结构是链表形式,查询较慢,增删速度快;Vector:底层是数组数据结构,线程同步。被ArrayList替代。

9、*枚举EnumerationVector特有的取出方式,枚举和迭代器其实是一样的,枚举是早期的,因为枚举的名称以及方法的名称都过长,所以被迭代器取代了。

代码:Vector v=new Vector();

v.add("day01");

v.add("day02");

v.add("day03");

v.add("day04");

//Enumeration是一个接口,称为枚举,与迭代器类似是Vector特有的取出方式

//它有两种方法:hasMoreElements()nextElements(),相当于迭代器的hasNextnext()

Enumeration en=v.elements();

while(en.hasMoreElements())

{

System.out.println(en.nextElement());

}

 

10、LinkedList特有的方法:

addFirst();  将元素插入列表头部

addLast();  将元素插入列表尾部

getFirst();  getLast();  获取元素但不删除元素,如果集合中没有元素,会出现NoSuchElementException

removeFirst(); removeLast();  获取元素,但元素被删除,如果集合中没有元素,则会抛出NoSuchElementException

 

JDK1.6出现了以下替代方法。

offerFirst();  将元素插入列表头部

offerLast();  将元素插入列表尾部

peekFirst();  peekLast();获取元素但不删除元素,如果集合中没有元素,会返回NULL

pollFirst();   pollLast();获取元素但是删除元素,如果集合中没有元素,会返回NULL

11、List集合判断元素是否相同,依据的是元素的equals方法。

调用contains();方法和remove();方法时都在底层自动调用了equals();方法

代码1:例如删除集合中重复的元素,该集合中的元素是字符串

public static ArrayList singleElement(ArrayList a)

{

ArrayList al=new ArrayList();

Iterator it=a.iterator();

//注意在迭代时循环中next调用一次,就要hasNext判断一次

while(it.hasNext())

{

Object obj=it.next();

if(!al.contains(obj))

al.add(obj);

}

return al;

}

代码2:同样删除集合中重复的元素,但该元素是对象;假设是人对象,如果人的姓名和年龄相同则代表元素重复,删除一个。这需要在定义Person类时,重写equals方法,还有打印时注意强制类型转换。

class Person{

private String name;

private int age;

Person(String name,int age)

{

this.name=name;

this.age=age;

}

//重写equals方法

public boolean equals(Object obj)

{

//(obj instanceof Person)表示obj这个对象是否是Person类的实例,是返回true,否则返回false

if(!(obj instanceof Person))

return false;

Person p=(Person)obj;

return this.name.equals(p.name)&&this.age==age;

}

public String getName()

{

return name;

}

public int getAge()

{

return age;

}

}

//判断集合中的元素是否相同的方法

public static ArrayList isSingleElement(ArrayList al)

{

ArrayList a2=new ArrayList();

 Iterator it=al.iterator();

 while(it.hasNext())

 {

 Object obj=it.next();

 if(!a2.contains(obj))

 a2.add(obj);

 

 }

 return a2;

}

//输出集合中的元素,其元素为对象的方法

public static void getSingleElement(ArrayList a)

{

Iterator it= a.iterator();

 while(it.hasNext())

 {

 Object obj=it.next(); //it.next()返回的是Object类型

 Person p=(Person)obj;//要使用Person类中的方法必须做强制转换

 System.out.printly(p.getName()+":"+p.getAge());

 }

}

public static void main(String[] args) {

 ArrayList al=new ArrayList();

 //像容器中添加人对象

 al.add(new Person("liyi",20));

 al.add(new Person("lier",20));

 al.add(new Person("lisan",24));

 al.add(new Person("liyi",20));

 al.add(new Person("lier",20));

 

 al=isSingleElement(al);

 getSingleElement(al);

}

 

12、SetSet集合的功能和Collection的功能一样,但Set集合的元素无序的,不可重复的。其实现的子类常见的有HashSetTreeSet,前者底层的数据结构是哈希表,线程非同步。后者底层的数据结构是二叉树,二叉树默认从小到大取。

其中哈希表的存储的元素的位置不是按存储的顺序存入的,而是按照存入元素哈希值存储的,但是如果两个对象的地址值相同,则会再判断两个对象是否是同一对象,如果是则不存入哈希表,如果位置一样,但不是同一对象则会存入哈希表,两个对象在同一地址值之上顺延。

13、HashSet是如何保证元素唯一性的?是通过元素的两个方法,hashCodeequals来完成。这两个方法都是在底层内部调用的,当元素存入哈希表时首先会调用hashCode方法来计算元素的哈希值,如果哈希值不同则直接存入哈希表,不再调用equals方法,如果哈希值相同,则调用equals方法来判断这两个元素是否相同,如果不相同则,则两个元素在同一地址上顺延,如果相同则不存入哈希表。

值得注意的是,对于判断元素是否存在,以及删除等操作,HashSet集合首先依赖的是hashCode方法,其次依赖的是equals方法。而ArrayList只依赖equals方法

一般如果存入的是自定义的对象,则一般要复写该类的hashCodeequals方法来提高效率。

代码: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;

}

//复写hashCode方法

public int hashCode()

{

//

System.out.println(this.name+"--"+this.age);

return name.hashCode()+age*3;//这个年龄乘以3是为了保证不同的元素有不同的哈希值

}

//复写equals方法

public boolean equals(Object obj)

{

if(!(obj instanceof Person))

return false;

System.out.println(this.name+"..equals.."+this.age);

Person p=(Person)obj;

return this.name.equals(p.name)&&this.age==p.age;

}

}

public class HashSetTest {

 

public static void printHashSet(HashSet hs)

{

Iterator it=hs.iterator();

while(it.hasNext())

{

Object obj=it.next();

Person p=(Person)obj;

System.out.println(p.getName()+":"+p.getAge());

}

}

public static void main(String[] args) {

HashSet hs=new HashSet();

hs.add(new Person("dashan",23));

hs.add(new Person("dashai",27));

hs.add(new Person("xiaotian",17));

hs.add(new Person("dashai",27));

hs.add(new Person("dashan",20));

       //判断元素是否存在

    System.out.println("dashan:"+hs.contains(new Person("dashan",23)));

    //删除元素

    hs.remove(new Person("xiaotian",17));

printHashSet(hs);

 

 

}

14、TreeSet:可以对set集合中的元素进行排序

值得注意的是,排序时,当主要条件相同时,一定要判断一下下次要条件。

当像TreeSet中存入自定义的对象时,自定义该对象的类时需要实现接口Comparable,并重写compareTo方法

如果想要按照存储的顺序取出,则重写的compareTo方法中只写return 1;即可,都存在了二叉树的右边,一次取出

//如果想按照存储的逆序取出,则compareTo方法中写return -1;即可,元素都排在二叉树的左边,从小到大,从下到上取出

代码:class Student implements Comparable{

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 compareTo(Object obj)

{

if(!(obj instanceof Student))

throw new RuntimeException("不是学生对象");

Student s=(Student)obj;

if(this.age>s.age)

return 1;

//当年龄相同,姓名不相同时,如果只判断年龄,另一个存入不进去,所以此时也应该判断一下另一个条件,方法一:

/*if(this.age==s.age&&this.name.equals(s.name))

return 0;*/

//判断次要条件 方法二:

if(this.age==s.age)

{

return this.name.compareTo(s.name);

}

if(this.age<s.age)

return -1;

return age;

}

}

public class TreeSetDemo1 {

 

public static void main(String[] args) {

TreeSet ts=new TreeSet();

ts.add(new Student("aa1",19));

ts.add(new Student("aa2",23));

ts.add(new Student("aa3",20));

ts.add(new Student("aa4",23));

Iterator it=ts.iterator();

while(it.hasNext())

{

Object obj=it.next();

Student stu=(Student)obj;

System.out.println(stu.getName()+":"+stu.getAge());

}

15、TreeSet:底层数据结构是二叉树。它保证唯一性的依据是:compareTo方法return0

TreeSet排序的第一种方法:让元素自身具备比较性。元素需要实现Comparable接口,覆盖comparaTo方法,这种方式也成为元素的自然顺序,或者叫默认顺序。

第二种排序方式:当元素自身不具备比较性,或者具备的比较性不是所需要的,这时需要让容器自身具备比较性。定义了比较器,将比较器对象作为参数传递给TreeSet的集合参数。

当两种排序到存在时以比较器为主

import java.util.*;

public class TreeSetTest {

 

/**

 * 按照字符串长度排序

 * @param args

 */

public static void main(String[] args) {

TreeSet ts=new TreeSet(new StrLenCompator());

ts.add("ahn");

ts.add("ybbf");

ts.add("cjiiuh");

ts.add("gjyia");

Iterator it=ts.iterator();

while(it.hasNext())

{

System.out.println(it.next());

}

}

}

class StrLenCompator implements Comparator

{

public int compare(Object o1,Object o2)

{

String s1=(String)o1;

String s2=(String)o2;

int num=new Integer(s1.length()).compareTo(new Integer(s2.length()));

//为了防止相同长度不同内容的字符串被删除

if(num==0)

return s1.compareTo(s2);

return num;

}

}

16、泛型:JDK1.5版本以后出现的新特性。用于解决安全问题,是一个安全机制。泛型的好处:

第一,将运行时期出现的ClassCastException,转移到了编译时期,方便与程序员解决问题,让运行事情问题减少,安全。

第二,避免了强制转换的麻烦

泛型格式:通过< >来定义要操作的引用数据类型。在使用Java提供的对象时,什么时候写泛型呢?

通常在集合框架中很常见,只要见到< >就是用来接收类型的。

当使用集合时,将集合中要存储的数据类型作为参数传递到< >中即可。

17、什么时候定义泛型类。

当类中要操作的引用数据类型不确定时(注意必须是引用数据类型,不能传递基本数据类型),早期定义Object来完成扩展,但是需要强制类型转换。现在使用泛型来扩展免去了强转的麻烦。

泛型中的术语

1ArrayList<E>整个成为泛型类型

2ArrayList<E>中的E成为类型变量或类型参数

3,整个ArrayList<Integer>成为参数化的类型

4ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数

5ArrayList<Integer>中的<>称为typeof,整体念做ArrayList typeof Integer。是什么类型的ArrayList

6ArrayList成为原始类型

7,参数化类型与原始化类型的兼容性。

参数化类型可以引用一个原始类型的对象,编译报告警告,例如

Collection<String> c=new Vector();

原始类型可以引用一个参数化类型的对象,编译报告警告,例如

Collection c=new Vector<String>();//如果原来的方法接受一个集合参数,新的类型也要能传进去。

8,参数化类型不考虑类型参数的继承关系

Vector<String> v=new Vector<Object>();//错误

Vector<Object> v=new Vector<String>();//错误

9,在创建数组实例时,数组的元素不能使用参数化的类型,例如,下面语句有错误:

Vector<Integer> vectorList[]=new Vector<Integer>[10];

 

18、泛型类定义的泛型在整个类中有效。如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同的方法可以操作不同的类型,而且类型还不确定。那么可以将泛型定义在方法上。

(特殊之处:静态方法不可以访问类上定义的泛型。如果静态方法操作的应用数据类型不确定,可以将泛型定义在静态方法上。静态泛型。

格式:public static <W> void f(W w)

{

System.out.println(w);

})

比如:class Demo{

public <T> void show(T t)

{

System.out.println("show:"+t);

}

public <Q> void print(Q q)

{

System.out.println("print:"+q);

}

}

Class A

{public static void main(String[] args) {

Demo d=new Demo();

d.show("come on");

d.show(new Integer(12));

d.print(1.3);

d.print("jiayou");}}

19、泛型可以定义在接口上。

Interface  Inter<T>

{ public void show(T t);} 

Class  InteIm implements Inter<String>

{public void show(String s)

{System.out.println(“show:”+t);}

}

20、泛型的限定:?表示通配符,也可以理解为占位符

? extends E :表示可以接收E类型或者E的子类型。上限

? super E :可以接收E类型或者E的父类型。 下限

要求:可以打印任意类型的集合,代码示例:

/**

 * @param args

 * 通配符:?可以引用其他各种参数化的类型,?同配股定义的变量主要用作引用,可以

 * 调用与参数化无关的方法,不能调用与参数化有关的方法。

*不能把通配符?给一个具体的类型,如果某个方法的返回类型是带?的,

*不能将它赋值给一个具体的类型

 */

//要求:打印任意类型的集合

public static void printCollection(Collection<?> c){

//c.add("string");错误,因为?表示不确定什么类型,而add方法的参数是有固定类型的

c.size();//没错,因为size方法没有参数,每个类型都有size方法

for(Object obj:c){

System.out.println(obj);

}

c=new HashSet<Date>();//这是可以的

}

 

代码:public class GenericDemo5 {

public static void main(String[] args) {

ArrayList<Person> al=new ArrayList<Person>();

al.add(new Person("abc1"));

al.add(new Person("abc2"));

al.add(new Person("abc3"));

ArrayList<Stu> al1=new ArrayList<Stu>();

al1.add(new Stu("bnoe1"));

al1.add(new Stu("bnoe2"));

al1.add(new Stu("bnoe3"));

printCol(al);

printCol(al1);

 

}

//此函数可以打印PersonPerson的子类

public static void printCol(ArrayList<? extends Person> a)

{

Iterator<? extends Person> it=a.iterator();

while(it.hasNext())

{

System.out.println(it.next().getName());

}

}

}

 

class Person{

private String name;

Person(String name)

{

this.name=name;

}

public String getName()

{

return name;

}

}

class Stu extends Person{

Stu(String name)

{

super(name);

}

}

 

20、Map集合的特Map<K,V>:该集合存储键值对。一对一往里存,而且保证键的唯一性。基本方法有:

1,添加:V put(K key,V value);将指定的值与此映射中的指定键相关联,put方法会返回这个键对应的原来的值

   void putAll(Map<? extends K,? extends V> m) 将指定映射中所有映射关系复制到此映射中

2,删除: void clear();清空集合 V remove(Object Key);将含有此键的映射关系移除

3,判断:containsKey(Object key):是否包含指定键  containsValue(Object value):是否包含指定值 。isEmpty();如果此映射未包含键—值映射关系。则返回true

4,获取:V get(Object key)返回此映射中指定键的值   int size();返回此集合中的映射关系数   values():返回此映射所包含的值的Collection视图。   entrySet()    keySet()

代码:public static void main(String[] args) {

Map<String,String> map=new HashMap<String,String>();

//像集合中添加元素

map.put("01","xc1");

map.put("02","zdf");

map.put("03","lulu");

//打印该集合

System.out.println(map);

//判断

System.out.println(map.containsKey("01"));

System.out.println(map.containsValue("lulu"));

//删除元素

System.out.println("remove:"+map.remove("02"));

//获取

System.out.println("get:"+map.get("03"));

//获取map集合中所有的值

Collection col=map.values();

System.out.println(col);

//添加元素时,如果出现添加时相同的键,那么后添加的值会覆盖原有的值

//并且put方法返回被覆盖的值

System.out.println("put1:"+map.put("02","ppq1" ));//输出null

System.out.println("put1:"+map.put("02","ppq2" ));//输出ppq1

System.out.println(map);

 

}

21、 * Map集合的两种取出方式:keySet和entrySet

* keySet:将map中所有的键存入到Set集合中。因为Set具备迭代器

* 所以可以通过迭代方式取出所有的键,再根据get方法获取每一个键对应的值

* Map集合的第一种取出原理:将map集合转成set集合,再通过迭代器取出

* Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到set集合中

* 而这个关系的数据类型就是:Map.Entry   关系对象Map.Entry获取到后就可以通过它 的getKey()和getValue()方法来获取关系中的键和值

Map.Entry<K,V>是一个接口,具有自己的方法有点像迭代器

public static void main(String[] args) {

Map<String,String> map=new HashMap<String,String>();

map.put("11""as1");

map.put("12""as2");

map.put("13""as3");

map.put("14""as4");

//通过keySet方法将所有的键取出,存放到Set集合中

Set<String> keySet=map.keySet();

//通过迭代器以及get方法将所有的键及其对应的值取出

Iterator<String> it=keySet.iterator();

while(it.hasNext())

{

String key=it.next();

String value=map.get(key);

System.out.println("key:"+key+",value:"+value);

}

 

//通过entrySet方法取出Map集合中的映射关系,存入到Set集合中

Map<Integer,String> map1=new HashMap<Integer,String>();

map1.put(1, "q1");

map1.put(2, "q2");

map1.put(3, "q3");

Set<Map.Entry<Integer, String>> entrySet=map1.entrySet();

 

//遍历结果时,可以用for循环

for(Map.Entry<String,Integer> me: entrySet){

System.out.println("key:"+me.getKey()+" value:"+me.getValue());

}

 

//可以用Iteraotr迭代器

Iterator<Map.Entry<Integer, String>> it1=entrySet.iterator();

while(it1.hasNext())

{

Map.Entry<Integer, String> me=it1.next();

Integer key1=me.getKey();

String value1=me.getValue();

System.out.println("key1:"+key1+"--value1:"+value1);

}

}

}

22/*练习:给一个字符串比如“fsdsjdjdaer”获取该字符串中的字母出现的次数

并且打印结果形式为:a(1)b(3)...

注意:字母和次数之间存在映射关系,应首先想到map集合,因为map集合中存放

的就是映射关系。

思路:

1,首先将字符串转换成字符数组。因为要对每一个字母进行操作

2,定义一个map集合,因为打印结果有顺序所以应使用TreeMap

3,将每一个字母作为键去查map集合。如果返回null,则证明该集合中没有该

字母的映射关系,则向集合中存入该字母和1。如果返回不是null,则证明该集合

中已存在此字母及其对应的次数,那么就获取该字母对应的次数进行自增,然后将

该字母和自增后的次数重新存入到map集合中*/

public class MapTest2 {

 

public static void main(String[] args) {

String s=getCharNum("bdkjee,aehadad");

System.out.println(s);

 

}

public static String getCharNum(String str)

{

//首先将字符串转换成字符数组

char[] ch=str.toCharArray();

//定义一个map集合,注意泛型类型的传入,不能用char等基本数据类型

TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();

//遍历字符数组,判断方法一

for(int i=0;i<ch.length;i++)

{

//如果该字符串中还有一些非字母类的字符比如逗号句号等,而我们在判断打印时不需要则

if(!(ch[i]>='a'&&ch[i]<='z'||ch[i]>='A'&&ch[i]<='Z'))

continue;

Integer value=tm.get(ch[i]);

if(value==null)

{

tm.put(ch[i], 1);

}

else

{

value=value+1;

tm.put(ch[i], value);

}

}

/*int count=0;

//遍历字符数组,判断   方法二  优化方法一

for(int i=0;i<ch.length;i++)

{

if((ch[i]>='a'&&ch[i]<='z'||ch[i]>='A'&&ch[i]<='Z'))

{

Integer value=tm.get(ch[i]);

//如果value不为空,则获取其值自增,如果value为空则不获取它的值,直接自增存入

if(value!=null)

count=value;

count=count+1;

tm.put(ch[i],count);

//注意需要将count清零

count=0;

}

}*/

//这样输出不符合题目要求的格式,所以需要使用map集合的那两种特殊的取出方式中的一种

System.out.println(tm);

//StringBuilder  字符串缓冲区的append方法可以以上述形式输出

StringBuilder sb=new StringBuilder();

Set<Map.Entry<Character,Integer>> entrySet=tm.entrySet();

Iterator<Map.Entry<Character,Integer>>it=entrySet.iterator();

while(it.hasNext())

{

Map.Entry<Character,Integer> me=it.next();

Character key=me.getKey();

Integer val=me.getValue();

sb.append(key+"("+val+")");

}

//因为sb是StringBulider类型所以需要将其转换成字符串用toString()方法

return sb.toString();

//return null;

}

}

23//Map扩展:一对多方法一    将下列映射关系存储,

"yureban"  "01"  "zs"

"yureban"  "02"  "lisi"

"jiuyeban"  "01"  "wangwu"

"jiuyeban"  "02"   "zhaoliu"

public class MapDemo3 {

    

public static void main(String[] args) {

HashMap<String,HashMap<String,String>> czbk=new HashMap<String,HashMap<String,String>>();

HashMap<String,String> yure=new HashMap<String,String>();

HashMap<String,String> jiuye=new HashMap<String,String>();

czbk.put("yureban", yure);

czbk.put("jiuyeban",jiuye);

yure.put("01""zs");

yure.put("02""lisi");

jiuye.put("01","wangwu");

jiuye.put("02","zhaoliu");

//遍历czbk集合,获取所有的教室

Iterator<String> it=czbk.keySet().iterator();

while(it.hasNext())

{

String roomName=it.next();

HashMap<String,String> room=czbk.get(roomName);

System.out.println(roomName);

getStudentInfo(room);

}

//getStudentInfo(yure);

//getStudentInfo(jiuye);

 

}

//打印教室里的所有学生

public static void getStudentInfo(HashMap<String,String> roomMap)

{

Set<String> keySet=roomMap.keySet();

Iterator<String> it=keySet.iterator();

while(it.hasNext())

{

String id=it.next();

String name=roomMap.get(id);

System.out.println(id+":"+name);

}

}

}

24 Map扩展一对多,一个学校有很多教室,一个教室有很多学生。教室有教室名,学生有学号和姓名.上面的代码形式不常用,通常将学生封装成对象

class Student1{

private String id;

private String name;

public Student1(String id,String name)

{

this.id=id;

this.name=name;

}

public String toString()

{

return id+"--"+name;

}

}

public class MapDemo3kuozhan {

 

public static void main(String[] args) {

HashMap<String,List<Student1>> hm=new HashMap<String,List<Student1>>();

List<Student1> yure=new ArrayList<Student1>();

List<Student1> jiuye=new ArrayList<Student1>();

yure.add(new Student1("01","zx"));

yure.add(new Student1("02","sx"));

jiuye.add(new Student1("01","lu"));

jiuye.add(new Student1("02","mei"));

hm.put("yureban", yure);

hm.put("jiuyeban", jiuye);

Set<String> keySet=hm.keySet();

Iterator<String> it1=keySet.iterator();

while(it1.hasNext())

{

String roomName=it1.next();

List<Student1> room=hm.get(roomName);

getStuInfo(room);

}

 

}

//取出教室中的学生,遍历List集合

public static void getStuInfo(List<Student1> list)

{

Iterator<Student1> it=list.iterator();

while(it.hasNext())

{

Student1 s=it.next();

System.out.println(s);

}

}

}

25、Collections工具类,该类中所有方法都是静态的,用类名直接调用。其中常用方法,sort()方法排序,max()方法求最大值,binarySearch()方法二分查找,fill()方法替换掉集合中的所有元素,repalaceAll()用一个新值替换集合中的旧值,reverse()反转,shuffle()把集合中的元素按照随机的方式进行排放。

代码1public static void sortDemo()

{

List<String> list=new ArrayList<String>();

list.add("abxd");

list.add("bss");

list.add("e");

list.add("oo");

list.add("bss");

//未排序之前

System.out.println(list);

//调用Collections的sort方法进行排序自然排序,不能给Set集合排序

Collections.sort(list);

System.out.println(list);

//按字符串长度排序则传入自定义比较器的对象

Collections.sort(list,new StrLenComparator());

System.out.println(list);

}

//如果想要对字符串按长度排序,则自定义比较器

class StrLenComparator implements Comparator<String>{

public int compare(String s1,String s2)

{

if(s1.length()>s2.length())

return 1;

if(s1.length()<s2.length())

return -1;

return s1.compareTo(s2);

}

}

代码2public static void maxDemo()

{

List<String> list=new ArrayList<String>();

list.add("abxd");

list.add("bss");

list.add("e");

list.add("oo");

list.add("bss");

Collections.sort(list);

//在自然排序的情况下获取最大值

String max=Collections.max(list);  //输出oo

System.out.println(max);

//在比较器规定的情况下获取最大值

String max1=Collections.max(list,new StrLenComparator());  //输出abxd

System.out.println(max1);

}

 

代码3public static void binarySearchDemo()

{

List<String> list=new ArrayList<String>();

list.add("abxd");

list.add("bss");

list.add("e");

list.add("oo");

list.add("bss");

Collections.sort(list,new StrLenComparator());

System.out.println(list);

int index=Collections.binarySearch(list,"e");//返回角标

System.out.println("index="+index);

int index1=halfSearch2(list,"bss",new StrLenComparator());

System.out.println("index1="+index1);

}

//二分查找的原理binarySearch(List<? extends Comparable<? super T>> list, T key

public static int halfSearch(List<String>list,String key)

{

int max,min,mid;

max=list.size()-1;

min=0;

//只要min下雨max就可以折半

while(min<=max)

{

mid=(max+min)>>1;  //相当于除以2

    String str=list.get(mid);

    int num=str.compareTo(key);

if(num>0)    //证明key在中间值左边,改变max值

max=mid-1;

else if(num<0)

min=mid+1;

else return mid;

}

return -min-1;   //min为插入点

}

//二分查找原理二,当比较对象不具备比较性时需要传入比较器

//binarySearch(List<? extends T> list, T key, Comparator<? super T> c)

public static int halfSearch2(List<String>list,String key,Comparator<String> cmp)

{

int max,min,mid;

max=list.size()-1;

min=0;

//只要min下雨max就可以折半

while(min<=max)

{

mid=(max+min)>>1;  //相当于除以2

    String str=list.get(mid);

    int num=cmp.compare(str,key);

if(num>0)    //证明key在中间值左边,改变max值

max=mid-1;

else if(num<0)

min=mid+1;

else return mid;

}

return -min-1;   //min为插入点

}

 

代码4public static void fillDemo()

{

ArrayList<String> al=new ArrayList<String>();

al.add("xiaxue");

al.add("zhongmou");

al.add("zijia");

System.out.println(al);//打印结果:[xiaxuezhongmouzijia]

//替换

Collections.replaceAll(al,"zhongmou","haha");

System.out.println(al);//打印结果:[xiaxuehahazijia]

//替换所有

Collections.fill(al, "erhuo");

System.out.println(al);//打印结果:[erhuoerhuoerhuo]

}

public static void reverseDemo()

{

ArrayList<String> al=new ArrayList<String>();

al.add("xiaxue");

al.add("zhongmou");

al.add("zijia");

System.out.println(al);//打印结果:[xiaxuezhongmouzijia]

//反转

Collections.reverse(al);

System.out.println(al);//打印结果:[zijiazhongmouxiaxue]

}

26、Collections工具类中的另外两个重要方法:

Collections工具类中的reverseOrder()方法:返回一个比较器,它强行反转实现 Comparable 接口那些对象 collection 上的自然顺序。

reverseOrder(Comparator<T> cmp) 方法:返回一个比较器,它强行反转指定比较器的顺序

代码:public class CollectionsDemo2 {

public static void main(String[] args) {

orderDemo();

 

}

public static void orderDemo()

{

TreeSet<String> ts=new TreeSet<String>();

ts.add("qq");

ts.add("kfdj");

ts.add("jfrod");

ts.add("djd");

System.out.println(ts);//打印结果是有顺序的,按照自然排序 [djdjfrodkfdjqq]

//要想让它按照自然排序的逆序输出,以前的做法是自定义比较器

TreeSet<String> ts1=new TreeSet<String>(new StrComparator());

ts1.add("qq");

ts1.add("kfdj");

ts1.add("jfrod");

ts1.add("djd");

System.out.println(ts1); //打印结果自然排序的逆序 [qqkfdjjfroddjd]

//但是这样需要重新定义比较器,比较麻烦,应首先想到Collections的reverseOrder()方法,该方法返回一个强行逆转的比较器

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

ts2.add("qq");

ts2.add("kfdj");

ts2.add("jfrod");

ts2.add("djd");

System.out.println(ts2); //打印结果同上[qqkfdjjfroddjd]

//按照长度排序,是由短到长的

TreeSet<String> ts3=new TreeSet<String>(new StrLengthComparator());

ts3.add("qq");

ts3.add("kfdj");

ts3.add("jfrod");

ts3.add("djd");

System.out.println(ts3);//打印结果[qqdjdkfdjjfrod]

//如果想要让它按照从长到短排序,而不改写比较器的代码,使用Collections的reverseOrder(Comparator<T> cmp)方法

TreeSet<String> ts4=new TreeSet<String>(Collections.reverseOrder(new StrLengthComparator()));

ts4.add("qq");

ts4.add("kfdj");

ts4.add("jfrod");

ts4.add("djd");

System.out.println(ts4);//打印结果[jfrodkfdjdjdqq]

}

class StrComparator implements Comparator<String>{

public int compare(String s1,String s2)

{

return s2.compareTo(s1);

}

}

//按照长度由短到长排序,自定义比较器

class StrLengthComparator implements Comparator<String>{

public int compare(String s1,String s2)

{

if(s1.length()>s2.length())

return 1;

else if(s1.length()<s2.length())

return -1;

return s1.compareTo(s2);

}

}

27Arrays:用于操作数组的工具类。里面都是静态方法 比如排序和搜索等各种方法

 * 一个比较特殊的方法:将数组转换成List集合。asList(T... a) 返回一个受指定数组支持的固定大小的列表

/*把数组变成集合的好处:可以使用集合的思想和方法来操作数组中的元素

注意:将数组变成集合不可以使用集合的增删操作,因为数组的长度是固定的

但是可以使用比如:contains(),get(),indexOf()等

*/

String[] arr1=new String[]{"ab","dfs","eef"};

List<String> list=Arrays.asList(arr1);

System.out.println(list);

 

28、 集合变数组:Collection接口中的toArray方法

 */

public static void main(String[] args) {

ArrayList<String> al=new ArrayList<String>();

al.add("abc1");

al.add("abc2");

al.add("abc3");

/*注意:1,指定类型的数组到底应定义多长?

当指定类型的数组长度小于集合的size,那么该方法内部会创建一个

新的数组;当指定类型的数组长度大于了集合的size,就不会创建新的数组,

而使用传递进来的数组。所以创建一个刚刚好的数组最优。即长度为list.size();

2,为什么要将集合变数组

为了限定对元素的操作,不要进行增删。

*/

String[] arr=al.toArray(new String[al.size()]);

System.out.println(Arrays.toString(arr));}

 

28/*高级for循环:JDK1.5  对迭代器进行了封装,简化书写

格式:

for(数据类型 变量名:被遍历的集合(Collection)或者数组){  }

此格式对集合进行遍历只能获取集合元素,但是不能对集合进行操作。

迭代器除了遍历,还可以对集合进行remove操作.如果使用ListIterator,

还可以在遍历过程中对集合进行增删改查等操作。

传统For循环和高级for有什么区别?

高级for有一个局限性,必须有被遍历的目标

 

建议在遍历数组时尽量使用传统for,因为传统for可以对角标进行操作

*/

public class ForEachDemo {

public static void main(String[] args) {

ArrayList<String> al=new ArrayList<String>();

al.add("asd1");

al.add("des2");

al.add("dif3");

for(String s:al)

{

System.out.println(s);//打印结果:asd1 des2 dif3

}

//对Map集合的打印,先转成Set集合再用高级for循环

HashMap<Integer,String> hm=new HashMap<Integer,String>();

hm.put(1, "a");

hm.put(2, "b");

hm.put(3, "c");

//方法一:keySet

Set<Integer> keySet=hm.keySet();

for(Integer i: keySet)

{

System.out.println(i+"::"+hm.get(i));

}

//方法二:entrySet

Set<Map.Entry<Integer,String>> entrySet=hm.entrySet();

for(Map.Entry<Integer,String> me:entrySet)

{

System.out.println(me.getKey()+"---"+me.getValue());

}

}

}

29、JDK1.5版本新特性:可变参数:int...arr

其实就是数组参数的简写形式。不用每一次都手动的建立数组对象。只要将要操作的元素作为参数传递即可。隐式将这些参数封装成立数组。

Public static void show(int...arr)

{

System.out.println(arr.length);

}

Public static void main(String[] args)

{

只要传入参数类型相同,可以可变长度,在底层自动封装成数组

show(1,2,3); //打印结果为3

show(1,2,3,4,5);//打印结果为5

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值