Java基础——集合List+Set+泛型+Map

 

1.   集合类概述

为什么出现集合类?

•面向对象语言对事物的体现都是以对象的形式,所以为了方便对多

个对象的操作,就对对象进行存储,集合就是存储对象最常用的一

种方式,不能存储基本数据类型,但是出现自动装箱后,可以存储基本数据类型。

数组和集合类同是容器,有何不同?

•数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。

数组中可以存储基本数据类型,集合只能存储对象。

集合类的特点

•集合只用于存储对象,集合长度是可变的,集合可以存储不同类型

的对象。

 

集合框架:集合体系,由一系列的集合容器共同组成;

 

为什么会出现这么多的容器呢?

因为每一个容器对数据的存储方式都有不同。这个存储方式称之为:数据结构;

 

2.   共性方法Collection+ArrayList+迭代

 

Collection定义了集合框架的共性功能。

1,添加

         add(e);

         addAll(collection);

 

2,删除

         remove(e);

         removeAll(collection);

         clear();

 

3,判断。

         contains(e);// 如果此 collection 包含指定的元素,则返回true。

         isEmpty();

 

4,获取

         iterator();

         size();

 

5,获取交集。

         retainAll();

 

6,集合变数组。

         toArray();

 

1,add方法的参数类型是Object。以便于接收任意类型对象。

 

2,集合中存储的都是对象的引用(地址)

注意:数组,集合中存储的不是对象实体,是内存地址;

 

为了操作集合中的元素,每个容器都有自己的内部类,完成了取出,判断等动作的定义;

这样取出方式就可以直接访问集合内容的元素;

每个容器的数据结构不同,

所以取出的动作细节不同,但有共性内容判断和取出

将共性内容抽取出来,形成Iterator接口

 

如何获取集合的对象呢?

通过迭代器。

 

什么是迭代器呢?

其实就是集合的取出元素的方式。

如同抓娃娃游戏机中的夹子。

 

迭代器是取出方式,会直接访问集合中的元素。

所以将迭代器通过内部类的形式来进行描述。

通过容器的iterator()方法获取该内部类的对象。

(与打印不同)

 

请看如下应用:

import java.util.*;
class  CollectionDemo
{
	public static void main(String[] args) 
	{
		
		method_toArray();
	}
public static void method_toArray()//toArray的使用
	{
		ArrayList al = new ArrayList();

		//1,添加元素。
		al.add("java01");//add(Object obj);
		al.add("java02");
		al.add("java03");
		al.add("java04");

		String s[]=(String[])al.toArray(new String[]{});
		System.out.print("\n\n以数组方式输出:");	
		for (int i = 0; i < s.length; i++) {	//输出字符串数组中的内容
			System.out.print(s[i] + "、");		//输出每一个元素
		}
	System.out.print("\n以对象数组方式输出:");	
	Object obj[]=al.toArray();
	for (int i=0;i<obj.length ;i++ )
	{
		System.out.print(obj[i] + "、");		//输出每一个元素
	}
	}

	public static void method_get()
	{
		ArrayList al = new ArrayList();

		//1,添加元素。
		al.add("java01");//add(Object obj);
		al.add("java02");
		al.add("java03");
		al.add("java04");

		/*
		Iterator it = al.iterator();//获取迭代器,用于取出集合中的元素。

		while(it.hasNext())//这种循环输出后,内存中仍有对象存在
		{
			sop(it.next());
		}
		*/

		for(Iterator it = al.iterator(); it.hasNext() ; )//it是局部变量,用完即消失
		{
			sop(it.next());
		}
	}


	public static void method_2()
	{
		ArrayList al1 = new ArrayList();

		al1.add("java01");
		al1.add("java02");
		al1.add("java03");
		al1.add("java04");
		ArrayList al2 = new ArrayList();

		al2.add("java03");
		al2.add("java04");
		al2.add("java05");
		al2.add("java06");

		
		//al1.retainAll(al2);//取交集,al1中只会保留和al2中相同的元素。
		al1.removeAll(al2);//al1中删除al2中存在的元素

		sop("al1:"+al1);
		sop("al2:"+al2);
	}

	public static void base_method()
	{
		//创建一个集合容器。使用Collection接口的子类。ArrayList
		ArrayList al = new ArrayList();

		//1,添加元素。
		al.add("java01");//add(Object obj);
		al.add("java02");
		al.add("java03");
		al.add("java04");

		//打印原集合。
		sop("原集合:"+al);

		//3,删除元素。
		//al.remove("java02");
		//al.clear();//清空集合。

		//4,判断元素。
		sop("java03是否存在:"+al.contains("java03"));
		sop("集合是否为空?"+al.isEmpty());


		//2,获取个数。集合长度。
		sop("size:"+al.size());

		//打印改变后的集合。
		sop(al);
	}

	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

3.   List集合+ListIterator迭代器

Collection

         |--List:元素是有序的,元素可以重复。因为该集合体系有索引(角标)。

                   |--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。初始化容量为10,50%延长数组;

                   |--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。

                   |--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。初始化容量为10,100%延长数组;

 

                  |--Set:元素是无序,元素不可以重复。、

 

List:

         特有方法。凡是可以操作角标的方法都是该体系特有的方法。

 

         add(index,element);

         addAll(index,Collection);

 

         remove(index);

 

         set(index,element);

         get(index):

         subList(from,to);

         listIterator();

         int indexOf(obj):获取指定元素的位置。

         ListIterator listIterator();

 

List集合特有的迭代器。ListIterator是Iterator的子接口。

 

在迭代时,不可以通过集合对象的方法操作集合中的元素。

因为会发生ConcurrentModificationException(并发)异常。

 

所以,在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,

只能对元素进行判断,取出,删除的操作,

如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator(列表迭代器)。

 

该接口只能通过List集合的listIterator方法获取。

 请看如下案例:

import java.util.*;

class ListDemo 

{

         public static void sop(Object obj)

         {

                   System.out.println(obj);

         }

         public static void method()

         {

                   

                   ArrayList al = new ArrayList();

 

                   //添加元素

                   al.add("java01");

                   al.add("java02");

                   al.add("java03");

                   

                   sop("原集合是:"+al);

                   //在指定位置添加元素。

                   al.add(1,"java09");

 

                   //删除指定位置的元素。

                   //al.remove(2);

 

                   //修改元素。

                   //al.set(2,"java007");

 

                   //通过角标获取元素。

                   sop("get(1):"+al.get(1));

 

                   sop(al);

 

                   //获取所有元素。

                   for(int x=0; x<al.size(); x++)

                   {

                            System.out.println("al("+x+")="+al.get(x));

                   }

 

                   Iterator it = al.iterator();

 

                   while(it.hasNext())

                   {

                            sop("next:"+it.next());

                   }

 

                   //通过indexOf获取对象的位置。

                   sop("index="+al.indexOf("java02"));

 

                   List sub = al.subList(1,3);

 

                   sop("sub="+sub);

         }

         

         public static void main(String[] args) 

         {

 

                   //演示列表迭代器。

                   ArrayList al = new ArrayList();

 

                   //添加元素

                   al.add("java01");

                   al.add("java02");

                   al.add("java03");

                   sop(al);

                   

                   ListIterator li = al.listIterator();

                   

                   //sop("hasPrevious():"+li.hasPrevious());//判断迭代前指针前面有没元素

                   //正向遍历

                   while(li.hasNext())

                   {

                            Object obj = li.next();

 

                            if(obj.equals("java02"))

                                      //li.add("java009");

                                     li.set("java006");

                   }

                   //逆向遍历

                   while(li.hasPrevious())

                   {

                            sop("pre::"+li.previous());

                   }

                   //sop("hasNext():"+li.hasNext());//判断迭代后指针后面有没元素

                   //sop("hasPrevious():"+li.hasPrevious());

 

                   sop(al);

 

                   /*

                   //在迭代过程中,准备添加或者删除元素。

 

                   Iterator it = al.iterator();

 

                   while(it.hasNext())

                   {

                            Object obj = it.next();

 

                            if(obj.equals("java02"))

                                     //al.add("java008");

                                     it.remove();//将java02的引用从集合中删除了。容器中的引用被删除,但是对象仍然在内存中;

 

                            sop("obj="+obj);

                   }

                   sop(al);

                   */

         }

}

4.   枚举的特点

枚举就是Vector特有的取出方式。

发现枚举和迭代器很像。

其实枚举和迭代是一样的。

 

因为枚举的名称以及方法的名称都过长。

所以被迭代器取代了。

枚举郁郁而终了。

应用: 

import java.util.*;

class VectorDemo 

{

         public static void main(String[] args) 

         {

                   Vector v = new Vector();

 

                   v.add("java01");

                   v.add("java02");

                   v.add("java03");

                   v.add("java04");

 

                   Enumeration en = v.elements();

 

                   while(en.hasMoreElements())

                   {

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

                   }

         }

}

5.   LinkedList

LinkedList:特有方法:

addFirst();

addLast();

 

getFirst();

getLast();

获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException

 

removeFirst();

removeLast();

获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementException

 

在JDK1.6出现了替代方法。

 

offerFirst();

offerLast();

 

peekFirst();

peekLast();

获取元素,但不删除元素。如果集合中没有元素,会返回null。

 

pollFirst();

pollLast();

获取元素,但是元素被删除。如果集合中没有元素,会返回null。

请看如下案例:

import java.util.*;

class LinkedListDemo 

{

         public static void main(String[] args) 

         {

                   LinkedList link = new LinkedList();

                   link.addLast("java01");

                   link.addLast("java02");

                   link.addLast("java03");

                   link.addLast("java04");

 

                   //sop(link);

//               sop(link.getFirst());

//               sop(link.getFirst());

                   //sop(link.getLast());

                   //sop(link.removeFirst());

                   //sop(link.removeFirst());

 

                   //sop("size="+link.size());

 

                   while(!link.isEmpty())

                   {

                            sop(link.removeLast());

                   }

         }

 

         public static void sop(Object obj)

         {

                   System.out.println(obj);

         }

}

6.   LinkedList模拟堆栈或者队列数据结构

使用LinkedList模拟一个堆栈或者队列数据结构。

 

堆栈:先进后出  如同一个杯子。

队列:先进先出 First in First out  FIFO如同一个水管。

 请看如下程序:

import java.util.*;

class myList 

{

         private LinkedList list;

         myList()

         {

                   list=new LinkedList();

         }

         public void myadd(Object obj)//增加

         {

                   list.addFirst(obj);

         }

         public Object getlist()//获取

         {

                   return list.removeFirst();

         }

         public int length()//长度

         {

                   return list.size();

         }

         public void myset(int x,Object obj)//改

         {

                   list.set(x,obj);

         }

         public boolean isnull()//判断是否空

         {

                   return list.isEmpty();

         }

}

class linkedtest

{

         public static void main(String[] args) 

         {

                   myList ml=new myList();

                   ml.myadd("java01");

                   ml.myadd("java02");

                   ml.myadd("java03");

                   ml.myset(1,"javatest");//修改

                   System.out.println(ml.length());

                   while(!ml.isnull())

                   {

                   System.out.println(ml.getlist());      

                   }

                   System.out.println(ml.length());

         }

 

}

7.   去除ArrayList中的重复元素(字符串)

import java.util.*;

/*

去除ArrayList集合中的重复元素。

 

*/

class test

{

         public static void main(String args[])

         {

                   ArrayList al=new ArrayList();

                   al.add("test01");

                   al.add("test01");

                   al.add("test02");

                   al.add("test03");

                   al.add("test04");

                   al.add("test04");

                   

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

                   Iterator it=al.iterator();

                   while(it.hasNext())

                   {

                            print(it.next()+"......"+it.next());//一次取出两个,集合中有奇数个元素就会抛出异常;

                   }

                   */

                   al=single(al);

                   print(al);

         }

 

         public static ArrayList single(ArrayList a)

         {

                   ArrayList newal=new ArrayList();

                   Iterator i=a.iterator();

                   while(i.hasNext())

                   {

                            Object obj=i.next();

                            if(!newal.contains(obj))

                            {

                                     newal.add(obj);

                            }

                   }

                   return newal;

         }

 

         public static void print(Object a)

         {

                   System.out.println(a);

         }

}

8.   去除ArrayList中的重复元素(对象)

/*

将自定义对象作为元素存到ArrayList集合中,并去除重复元素。

 

比如:存人对象。同姓名同年龄,视为同一个人。为重复元素。

 

思路:

1,对人描述,将数据封装进人对象。

2,定义容器,将人存入。

3,取出。(注意类型转换)

4,定义删除重复的方法single。

5,重写equals方法,实现自己的比较规则,比较name和sex(此方法自动调用)

5,调用方法,删除重复元素

6,(小插曲),探究remove方法

 

Person继承Object,每个对象都有比较方法equals,比较的是内存地址,

注意:

String中的equals比较的是数值

 

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

其他集合的方法不同。

 

调用contains()方法时equals方法是底层自动调用;

*/

import java.util.*;

class Person

{

         private String name;

         private String sex;

         Person(String name,String sex)

         {

                   this.name=name;

                   this.sex=sex;

         }

         public String getName()

         {

                   return name;

         }

         public String getSex()

         {

                   return sex;

         }

 

         public boolean equals(Object o)

         {        

                   //限制比较的对象类别为Person

                   if(!(o instanceof Person))

                            return false;

                   Person p=(Person)o;

 

                   System.out.println(this.name+"....."+p.name);//展示比较过程

                   /*比较过程:01对象进来-->02对象进来(02对象调用equals,与01比较)-->03对象进来(与01比较,再与02比较)

         结合删除重复元素的原理图更容易理解

         */

                   return this.name.equals(p.name)&&this.sex.equals(p.sex);

         }

}

class ArrayList_t2

{

 

         public static void main(String[] args) 

         {

                   ArrayList al=new ArrayList();

                   al.add(new Person("xiaoming01","M"));

                   al.add(new Person("xiaoming02","M"));

                   al.add(new Person("xiaoming02","M"));

                   al.add(new Person("xiaoming03","M"));

                   al.add(new Person("xiaoming04","F"));

 

                   al=single(al);

                   //直接调用single无法实现,不知道比较姓名,性别。比较的是对象是否相同

                   //对象的比较,调用equals方法,此方法比较的是内存地址,new出的对象地址都不同

                   //所以重写equals方法,按照name和sex比较

                   print("--------remove-----------");

                   print("remove 02 :"+al.remove(new Person("xiaoming02","M")));

                   //remove方法底层也是依赖于元素的equals方法,能自动调用。没有重写equals方法的话就相当于创建了一个新对象,内存地址值不同,remove()方法返回false,删除失败

 

                   Iterator it = al.iterator();

                   while(it.hasNext())

                   {

                            //print(it.next.getName());//编译失败:it.next()返回是Object,没有此方法,无法识别的getName()方法;

                            //对象直接输出的,应该将Object类型转成Person,才能调用getName();

                            Person p = (Person)it.next();

                            print(p.getName()+"+"+p.getSex());

                   }

         }

 

         public static void print(Object obj)

         {

                   System.out.println(obj);

         }

         public static ArrayList single(ArrayList a)

         {

                   ArrayList newal=new ArrayList();

                   Iterator i=a.iterator();

                   while(i.hasNext())

                   {

                             Object obj=i.next();

                            if(!newal.contains(obj))//通过调用contains()方法,底层就是自动调用equals方法

                                     newal.add(obj);

                   }

                   return newal;

         }

}

9.   Set

概述:

|--Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。重复的元素不能存入。但是重复对象的筛选,要复写hascode()方法,重算哈希值。复写equals()方法。调用contains()方法,

         |--HashSet:底层数据结构是哈希表。是线程不安全的。不同步。存取速度快。

                            HashSet是如何保证元素唯一性的呢?

                            是通过元素的两个方法,hashCode和equals来完成。分别判断哈希值和对象。

                            如果元素的HashCode值相同,才会判断equals是否为true。

                            如果元素的hashcode值不同,不会调用equals。

 

                            注意,对于判断元素是否存在contains(),以及删除remove()等操作,依赖的方法是元素的hashcode()和equals()方法。

                            与ArrayList不同;

 

         |--TreeSet:

 

Set集合的功能和Collection是一致的。

 

往hashSet集合中存入自定对象过程分析

请看如下代码:

import java.util.*;

/*

往hashSet集合中存入自定对象

姓名和年龄相同为同一个人,重复元素。

*/

class HashSetTest 

{

         public static void sop(Object obj)

         {

                   System.out.println(obj);

         }

         public static void main(String[] args) 

         {

                   HashSet hs = new HashSet();

 

                   hs.add(new Person("a1",11));

                   hs.add(new Person("a2",12));

                   hs.add(new Person("a3",13));

                   //hs.add(new Person("a2",12));

//               hs.add(new Person("a4",14));

 

                   //sop("a1:"+hs.contains(new Person("a2",12)));//判断元素是否存在

                            

//               hs.remove(new Person("a4",13));//删除操作

                   

                   Iterator it = hs.iterator();

                   while(it.hasNext())

                   {

                            Person p = (Person)it.next();

                            sop(p.getName()+"::"+p.getAge());

                   }

         }

}

class Person

{

         private String name;

         private int age;

         Person(String name,int age)

         {

                   this.name = name;

                   this.age = age;

         }

         

         public int hashCode()//重写方法,自定义哈希值

         {

                   System.out.println(this.name+"....hashCode");

                   return name.hashCode()+age*37;// *37是任意的,为了避免哈希值的相同做的运算

//字符串也有自己的hashcode()方法;

         }

 

         public boolean equals(Object obj)

         {

 

                   if(!(obj instanceof Person))

                            return false;

 

                   Person p = (Person)obj;

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

 

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

         }

 

         public String getName()

         {

                   return name;

         }

         public int getAge()

         {

                   return age;

         }

}

10.   集合框架(TreeSet+存储自定义对象)

概述:

|--Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。重复的元素不能存入。但是重复对象的筛选,要复写hascode()方法,重算哈希值。复写equals()方法。调用contains()方法,

         |--HashSet:底层数据结构是哈希表。是线程不安全的。不同步。存取速度快。

                            HashSet是如何保证元素唯一性的呢?

                            是通过元素的两个方法,hashCode和equals来完成。分别判断哈希值和对象。

                            如果元素的HashCode值相同,才会判断equals是否为true。

                            如果元素的hashcode值不同,不会调用equals。

 

                            注意,对于判断元素是否存在contains(),以及删除remove()等操作,依赖的方法是元素的hashcode()和equals()方法。

                            与ArrayList不同;

 

         |--TreeSet:可以对Set集合中的元素进行排序。

                                    底层数据结构是二叉树。

                                    保证元素唯一性的依据:

                                     compareTo方法return 0.

 

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

                                    元素需要实现Comparable接口,覆盖compareTo方法。

                                    也种方式也成为元素的自然顺序,或者叫做默认顺序。

 

                                     TreeSet的第二种排序方式。

                                    当元素自身不具备比较性时,或者具备的比较性不是所需要的。(两个人比身高)这时就需要让集合自身具备比较性。

                                    在集合初始化时,就有了比较方式。(如:两个人用刻度尺-比较器比身高)

 

Set集合的功能和Collection是一致的。

需求:

往TreeSet集合中存储自定义对象学生。

想按照学生的年龄进行排序。

 

记住,排序时,当主要条件相同时,一定判断一下次要条件。

 

如:

class TreeSetDemo 

{

         public static void main(String[] args) 

         {

                   TreeSet ts = new TreeSet();

 

                   ts.add(new Student("lisi02",22));

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

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

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

                   //ts.add(new Student("lisi007",20));

                   //ts.add(new Student("lisi01",40));

 

                   Iterator it = ts.iterator();

                   while(it.hasNext())

                   {

                            Student stu = (Student)it.next();

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

                   }

         }

}

 

 

class Student implements Comparable//该接口强制让学生具备比较性。

{

         private String name;

         private int age;

 

         Student(String name,int age)

         {

                   this.name = name;

                   this.age = age;

         }

 

         public int compareTo(Object obj)

         {

 

                   //return 0;

                   

                   if(!(obj instanceof Student))

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

                   Student s = (Student)obj;

 

                   System.out.println(this.name+"....compareto....."+s.name);

                   if(this.age>s.age)

                            return 1;

                   if(this.age==s.age)

                   {

                            return this.name.compareTo(s.name);//调用String类的自身比较方法

                   }

                   return -1;

                   /**/

         }

 

         public String getName()

         {

                   return name;

 

         }

         public int getAge()

         {

                   return age;

         }

}


 

提示:

当存的是字符串对象时,调用默认的比较方法,按照ASCII玛进行自然排序;

存的是自定义对象,复写compareTo()方法,当主要条件相同时,一定判断一下次要条件;

如果要按怎么存进去就怎么取出来,则复写compareTo()方法,return 1即可,倒序的话就return -1;

11.    二叉树+ 实现Comparator方式排序

 

通过treeset,提高比较效率;

大的数在右边,小的数在左边,默认取数时从左到右;

 

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

这时需要让容器自身具备比较性。

定义一个比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。

 

当两种排序(元素自身具备比较性的排序和容器具备比较性的排序)都存在时,以比较器为主。

 

定义比较器:定义一个类,实现Comparator接口,覆盖compare方法。

 

注意:

compareable接口,覆盖compareTo()方法;

Comparator接口,覆盖compare方法

字符串自身具备compareTo()方法

 

请看如下案例:

class Student implements Comparable//该接口强制让学生具备默认的比较性。

{

         private String name;

         private int age;

 

         Student(String name,int age)

         {

                   this.name = name;

                   this.age = age;

         }

 

         public int compareTo(Object obj)

         {

 

                   //return 0;

                  

                   if(!(obj instanceof Student))

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

                   Student s = (Student)obj;

 

                   //System.out.println(this.name+"....compareto....."+s.name);

                   if(this.age>s.age)

                            return 1;

                   if(this.age==s.age)

                   {

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

                   }

                   return -1;

                   /**/

         }

 

         public String getName()

         {

                   return name;

 

         }

         public int getAge()

         {

                   return age;

         }

}

class TreeSetDemo2 

{

         public static void main(String[] args) 

         {

                   TreeSet ts = new TreeSet();

                   // TreeSet ts = new TreeSet(new MyCompare());//加上比较器进行排序

                   ts.add(new Student("lisi02",22));

                   ts.add(new Student("lisi02",21));

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

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

                   ts.add(new Student("lisi06",18));

                   ts.add(new Student("lisi06",18));

                   ts.add(new Student("lisi007",29));

                   //ts.add(new Student("lisi007",20));

                   //ts.add(new Student("lisi01",40));

 

                   Iterator it = ts.iterator();

                   while(it.hasNext())

                   {

                            Student stu = (Student)it.next();

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

                   }

         }

}

 

class MyCompare implements Comparator//定义比较器进行排序

{

         public int compare(Object o1,Object o2)

         {

                   Student s1 = (Student)o1;

                   Student s2 = (Student)o2;

 

                   int num = s1.getName().compareTo(s2.getName());//字符串比较

                   if(num==0)//当主要条件相同,比较次要条件

                   {

                            //整数的对象包装类有比较方法,所以将整数封装成Integer;

                            return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));

                            /*

                            if(s1.getAge()>s2.getAge())

                                     return 1;

                            if(s1.getAge()==s2.getAge())

                                     return 0;

                            return -1;

                            */

                   }

 

                   

                   return num;

 

         }

}

 

12.   MAP集合概述+子类对象特点+共性方法

Map集合:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。

         1,添加。

                   put(K key, V value),有返回值

                   putAll(Map<? extends K,? extends V> m)

 

         2,删除。

                   clear()

                   remove(Object key)

        

         3,判断。

                   containsValue(Object value)

                   containsKey(Object key)

                   isEmpty()

 

 

         4,获取。

                   get(Object key)

                   size()

                   values()

 

                   entrySet()

                   keySet()

 

Map

         |--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低。

         |--HashMap:底层是哈希表数据结构,允许使用 null值和 null 键,该集合是不同步的。将hashtable替代,jdk1.2.效率高。

         |--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。

 

 

和Set很像。

其实大家,Set底层就是使用了Map集合。

 

请看如下案例:

import java.util.*;

class  MapDemo

{

         public static void main(String[] args) 

         {

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

 

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

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

                  System.out.println("put:"+map.put("01","zhangsan1"));

                   System.out.println("put:"+map.put("01","wnagwu"));

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

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

 

                   System.out.println("containsKey:"+map.containsKey("022"));

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

 

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

 

                   map.put("04",null);

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

                   //可以通过get方法的返回值来判断一个键是否存在。通过返回null来判断。返回NULL代表不存在或者值为null;

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

                   Collection<String> coll = map.values();

 

                   System.out.println(coll);

                   System.out.println(map);
         }

}

13.    Keyset+entryset

keyset方法案例

EntrySet方法案例

map集合的两种取出方式:

1,Set<k> keySet:将map中所有的键存入到Set集合。因为set具备迭代器。

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

                  

 

         Map集合的取出原理:将map集合转成set集合。在通过迭代器取出。

 

 

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

                                    而这个关系的数据类型就是:Map.Entry

 

                                     Entry其实就是Map中的一个static内部接口。

                                    为什么要定义在内部呢?

                                    因为只有有了Map集合,有了键值对,才会有键值的映射关系。

                                    关系属于Map集合中的一个内部事物。

                                    而且该事物在直接访问Map集合中的元素。

 

 

请看应用:

import java.util.*;

class MapDemo2 

{

         public static void main(String[] args) 

         {

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

 

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

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

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

                   map.put("04","zhangsan4");

 

                   //将Map集合中的映射关系取出。存入到Set集合中。

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

 

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

 

                   while(it.hasNext())

                   {

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

                            String key = me.getKey();

                            String value = me.getValue();

 

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

 

                   }

 

                   /*

                   //先获取map集合的所有键的Set集合,keySet();

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

 

                   //有了Set集合。就可以获取其迭代器。

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

 

                   while(it.hasNext())

                   {

                            String key = it.next();

                            //有了键可以通过map集合的get方法获取其对应的值。

                            String value  = map.get(key);

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

                   }

 

                   */

 

         }

}

 

 

/*

Map.Entry 其实Entry也是一个接口,它是Map接口中的一个内部接口。

 

interface Map

{

         public static interface Entry

         {

                   public abstract Object getKey();

                   public abstract Object getValue();

 

         }

}

 

class HashMap implements Map

{

         class Hahs implements Map.Entry

         {

                   public  Object getKey(){}

                   public  Object getValue(){}

         }

         

}

*/

14.   Map练习

/*

每一个学生都有对应的归属地。

学生Student,地址String。

学生属性:姓名,年龄。

注意:姓名和年龄相同的视为同一个学生。

保证学生的唯一性。

 

 

 

1,描述学生。

 

2,定义map容器。将学生作为键,地址作为值。存入。

 

3,获取map集合中的元素。

 

*/

 

import java.util.*;

class Student implements Comparable<Student>

//如果一个类会产生多个对象,最好让其具备自然顺序

,实现comparable接口,复写compareTo()方法,hashcode()和equals()方法

{

         private String name;

         private int age;

         Student(String name,int age)

         {

                   this.name = name;

                   this.age = age;

         }

         

         public int compareTo(Student s)

         {

                   int num = new Integer(this.age).compareTo(new Integer(s.age));

 

                   if(num==0)

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

                   return num;

         }

         //为了限制数量,排除重复的数据,复写hashcode()和equals()方法

         public int hashCode()

         {

                   return name.hashCode()+age*34;

         }

         public boolean equals(Object obj)

         {

                   if(!(obj instanceof Student))

                            throw new ClassCastException("类型不匹配");

 

                   Student s = (Student)obj;

 

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

                   

 

         }

         public String getName()

         {

                   return name;

         }

         public int getAge()

         {

                   return age;

         }

         public String toString()

         {

                   return name+":"+age;

         }

}

 

 

 

class  MapTest

{

         public static void main(String[] args) 

         {

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

 

                   hm.put(new Student("lisi1",21),"beijing");

                   hm.put(new Student("lisi1",21),"tianjin");

                   hm.put(new Student("lisi2",22),"shanghai");

                   hm.put(new Student("lisi3",23),"nanjing");

                   hm.put(new Student("lisi4",24),"wuhan");

 

                   //第一种取出方式 keySet

 

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

 

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

 

                   while(it.hasNext())

                   {

                            Student stu = it.next();

                            String addr = hm.get(stu);

                            System.out.println(stu+".."+addr);

                   }

 

 

                   //第二种取出方式 entrySet

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

 

                   Iterator<Map.Entry<Student,String>> iter = entrySet.iterator();

                   

                   while(iter.hasNext())

                   {

                            Map.Entry<Student,String> me = iter.next();

                            Student stu = me.getKey();

                            String addr = me.getValue();

                            System.out.println(stu+"........."+addr);

                   }

         }

} 

15.   HashMap练习

/*4、用一个方法调用随机传入的字符串、(hashmap)把字符串里的!@#$替换为1234,去空格,并且把该字符串的前半部分截取出来全部小写,后半部分全部大写。

【map的使用,字符串的替换截取大小写转换】

您输入的是:Asw@rer$eaw!we      

asw2rer  

4EAW1WE*/

publicclass Demo

{

    

 publicstaticvoid main(String args[])

 {

     Scanner s = new Scanner(System.in);

     String str = s.next();

     System.out.println("您输入的是:"+str);

     Demo d= new Demo();

     System.out.println("处理后为:\n"+d.GetString(str));

 }

 public String GetString(String str)

 {

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

     map.put("!","1");

     map.put("@","2");

     map.put("#","3");

     map.put("$","4");

     

     char ch[]= newchar[str.length()];

     ch = str.toCharArray();

     String result="";

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

     {

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

         //有了Set集合。就可以获取其迭代器。

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

           while(it.hasNext())

           {

              String key = it.next();

              //有了键可以通过map集合的get方法获取其对应的值。

              String value  = map.get(key);

              if((ch[i]+"").equals(key))

              {

                  ch[i]=(value+"").charAt(0);

              }

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

           }

 

        if(i<(ch.length+1)/2)

        {

           result = result+(ch[i]+"").toLowerCase();

        }

        elseif (i==(ch.length+1)/2)

        {

            

            result =result+"\n"+(ch[i]+"").toUpperCase(); 

        } 

        else

                   result = result+(ch[i]+"").toUpperCase();

     }

     return result;

 }

} 

16.   TreepMap练习

/*
需求:对学生对象的年龄进行升序排序。

因为数据是以键值对形式存在的。
所以要使用可以排序的Map集合。TreeMap。
*/
import java.util.*;

class StuNameComparator implements Comparator<Student>
//按姓名排序,定义比较器
{
	public int compare(Student s1,Student s2)
	{
		int num = s1.getName().compareTo(s2.getName());
		if(num==0)
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));

		return num;
	}
}


class  MapTest2
{
	public static void main(String[] args) 
	{
		TreeMap<Student,String> tm = new TreeMap<Student,String>(new  
StuNameComparator());

		tm.put(new Student("blisi3",23),"nanjing");
		tm.put(new Student("lisi1",21),"beijing");
		tm.put(new Student("alisi4",24),"wuhan");
		tm.put(new Student("lisi1",21),"tianjin");
		tm.put(new Student("lisi2",22),"shanghai");

		
		Set<Map.Entry<Student,String>> entrySet = tm.entrySet();

		Iterator<Map.Entry<Student,String>> it = entrySet.iterator();

		while(it.hasNext())
		{
			Map.Entry<Student,String> me = it.next();

			Student stu = me.getKey();
			String addr = me.getValue();
			System.out.println(stu+":::"+addr);
		}
	}
}

17.   TreeMap练习-字母出现的次数

/*

练习:

"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。

 

希望打印结果:a(1)c(2).....

 

通过结果发现,每一个字母都有对应的次数。

说明字母和次数之间都有映射关系。

 

注意了,当发现有映射关系时,可以选择map集合。

因为map集合中存放就是映射关系。

 

 

什么使用map集合呢?

当数据之间存在这映射关系时,就要先想map集合。

 

思路:

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

 

2,定义一个map集合,因为打印结果的字母有顺序,所以使用treemap集合。

 

3,遍历字符数组。

         将每一个字母作为键去查map集合。

         如果返回null,将该字母和1存入到map集合中。

         如果返回不是null,说明该字母在map集合已经存在并有对应次数。

         那么就获取该次数并进行自增。,然后将该字母和自增后的次数存入到map集合中。覆盖掉原来键

所对应的值。

 

4,将map集合中的数据变成指定的字符串形式返回。

 

 

 

*/

import java.util.*;

class  MapTest3

{

         public static void main(String[] args) 

         {

                   String s= charCount("ak+abAf1c,dCkaAbc-defa");

                   System.out.println(s);

         }

         

         public static String charCount(String str)

         {

                   char[] chs = str.toCharArray();

 

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

                   //怎么实现排序?character实现了comparable接口,具备默认的自然排序

                   

                   int count = 0;//定义在外面,只开辟了一次空间。定义在循环里面,空间开了又关,

影响效率;

                   for(int x=0; x<chs.length; x++)

                   {

                            

 

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

                                     continue;//排除字母之外的字符

 

                            Integer value = tm.get(chs[x]);

 

                            /*

                            if(value==null)

                            {

                                     tm.put(chs[x],1);

                            }

                            else

                            {

                                     value = value + 1;

                                     tm.put(chs[x],value);

                            }

                            //put方法用了两次,重复。可以优化,用count变量

                            */

                            

                            if(value!=null)

                                     count = value;

                            count++;

                            tm.put(chs[x],count);//直接往集合中存储字符和数字,为什么可以,因为自

动装箱。

 

                            count = 0;//循环一次后需要清零

                            

                   }

 

                   //System.out.println(tm);

                   //遍历完想要存起来,可用缓冲区(什么类型都能存,而且输出String类型)

 

                   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 ch = me.getKey();

                            Integer value = me.getValue();

                            sb.append(ch+"("+value+")");

                   }

 

 

 

                   return sb.toString();//该方法返回string类型,sb返回的是stringbuilder,所以要调

用tostring方法;

         }
}

18.   Map扩展

map扩展知识。

 

map集合被使用是因为具备映射关系。

 

 

应用比较多的是一对多的映射关系,这就可以通过嵌套的形式将多个映射定义到一个大的集合中,并将大的集合分级处理,形成一个体系。

 

请看实例:

/*

需求:一个学校有多个教室。每一个教室都有名称。

 

"yureban"   Student("01" "zhangsan");

 

"yureban" Student("02" "lisi");

 

"jiuyeban" "01" "wangwu";

"jiuyeban" "02" "zhaoliu";

*/

 

import java.util.*;

 

class Student

{

         private String id;

         private String name;

         Student(String id,String name)

         {

                   this.id = id;

                   this.name = name;

         }

         public String toString()

         {

                   return id+":::"+name;

         }

}

class  MapDemo3

{

         //学生信息直接用list集合存储

         public static void demo()

         {

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

 

                   List<Student> reyu = new ArrayList<Student>();

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

 

                   czbk.put("yureban",reyu);

                   czbk.put("jiuyeban",jiuye);

 

                   reyu.add(new Student("01","zhagnsa"));

                   reyu.add(new Student("04","wangwu"));

                   jiuye.add(new Student("01","zhouqi"));

                   jiuye.add(new Student("02","zhaoli"));

 

 

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

 

                   while(it.hasNext())

                   {

                            String roomName = it.next();

                            List<Student> room = czbk.get(roomName);

                            

                            System.out.println(roomName);

                            getInfos(room);

                   }

 

                   

 

         

         }

         public static void getInfos(List<Student> list)

         {

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

                   while(it.hasNext())

                   {

                            Student s = it.next();

                            System.out.println(s);

                   }

         }

 

 

 

 

         public static void main(String[] args) 

         {

                    demo();

                   

                   /*

                   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","zhagnsan");

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

 

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

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

 

 

                   //取出所有学生

                   //遍历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(jiuye);//取出班级的学生

//               getStudentInfo(yure);

*/

                   

         }

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

         {

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

 

                   while(it.hasNext())

                   {

                            String id = it.next();

                            String name = roomMap.get(id);

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

                   }

         }

} 


 

 


 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值