集合及jdk部分新特性

 

一集合类概述

1.为什么出现集合类?

        面向对象语言对事物的体现都是以对象的形式对象都是确定性的可以区分的,所以可以存储起来,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用 的一种方式。

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

        数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象

注意:

集合中为什么不能存放基本数据类型?

集合中存放的可都是对象的引用,实际内容都在堆上面或者方法区里面,但是基本数据类型是在栈上分配空间的。随时就被收回的,是不确定的,集合只存储确定的元素。但是通过自动包装类就可以把基本类型转为对象类型,存放引用就解决了这个问题。

 

首先,集合的存在就是为了方便对多个对象的操作才出现的,集合是存储对象最常用的一种方式,也就是说,集合的从有到无都是因为对象,人们发现要保存多个对象很麻烦,于是便发明了集合,集合是依赖对象而生的,所以就对基本数据类型"不感兴趣",但是,现在基本数据类型都有了其对应的封装的对象,而且有了自动拆箱和装箱功能,基本数据类型和其对应对象之间的转换变得很方便,想把基本数据类型存入集合中,直接存就可以了,系统会自动将其装箱成封装类

然后加入集合当中

 

例如:下面的代码中,我就直接把int类型加入了集合中,java会自动将int类型包装成Integer对象,再装入集合中

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

list.add(1);

//打印结果为1


2.集合类的特点

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

集合框架图:

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

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

二、集合框架共性方法

1.集合类的由来:
对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定。
就使用集合容器进行存储。
集合特点:
(1).用于存储对象的容器。
(2).集合的长度是可变的。
(3).集合中不可以存储基本数据类型值。
集合容器因为内部的数据结构不同,有多种具体容器。
不断的向上抽取,就形成了集合框架。
Collection
|--List:有序(存入和取出的顺序一致),元素都有索引(角标),元素可以重复。
|--Set:元素不能重复,无序。
框架的顶层Collection接口:
Collection的常见方法:
(1)添加。
boolean add(Object obj):
boolean addAll(Collection coll):
(2)删除。
boolean remove(object obj):
boolean removeAll(Collection coll);
void clear();
(3)判断:
boolean contains(object obj):
boolean containsAll(Colllection coll);
boolean isEmpty():判断集合中是否有元素。
(4)获取:
int size():
Iterator iterator():取出元素的方式:迭代器。
该对象必须依赖于具体容器,因为每一个容器的数据结构都不同。
所以该迭代器对象是在容器中进行内部实现的。
对于使用容器者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器的对象即可,
也就是iterator方法。
Iterator接口就是对所有的Collection容器进行元素取出的公共接口。
其实就是抓娃娃游戏机中的夹子!
(5)其他:
boolean retainAll(Collection coll);取交集。
Object[] toArray():将集合转成数组。

注意:add方法的参数类型是object,以便于接受任意类型对象

           集合中存储的都是对象的引用地址:举例:当在集合中存入一个Person类对象,实际存入集合的是对象的引用地址。如图:

 

三、迭代器的理解

1.什么是迭代器?

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

(1)当每个容器都有存和取得动作,但是每个容器存取的动作又不一样时,当不足以用一个函数来描述,需要用多个功能来体现,所以就将取出这个动作封装成一个对象来描述。就把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内部的元素。那么取出方式就被定义成了内部类。

(2)而每一个容器的数据结构不同,所以取出的动作细节也不一样。但是都具有共性内容:判断和取出。那么就可以将这些共性抽取。

(3)那么这些内部类都符合一个规则(或者说都抽取出来一个规则)。该规则就是Iterator。通过一个对外提供的方法:iterator();,来获取集合的取出对象。

       因为Collection中有iterator方法,所以每一个子类集合对象都具备迭代器。

 

利用迭代器获取容器对象格式:

// 迭代器对象是通过容器的内部类方法获取出来的,返回的是Iterator接口的子类对象。利用了多态机制。

Iterator it = al.iterator();

//利用迭代器的方法判断时候有下一个元素
    while(it.hasNext())
    {

//把对象取出,对象都是object类型的子类;
    Object obj=it.next();
    }

注意:itnext()取数据时,是有游标的,第一次指的是,

三、List集合

1.List:元素是有序的,元素可以重复。因为该集合体系有索引。

            |--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。

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

            |--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。

2.List特有方法:

这些方法特点:都可以操作角标

(1)

        booleanadd(index,element);//指定位置添加元素

        BooleanaddAll(index,Collection);//在指定位置增加给定集合中的所有元素,若省略位置参数,则在当前集合的后面依次添加元素

(2)

        Booleanremove(index);//删除指定位置的元素

(3)

        set(index,element);//修改指定位置的元素。

(4)

        get(index);//通过角标获取元素

        subList(from,to);//获取部分对象元素

(5)其他

        listIterator();//List特有的迭代器

        indexOf(obj);//获取元素第一次出现的位置,如果没有则返回-1

注:List集合判断元素是否相同,移除等操作,依据的是元素的equals方法。

       List集合在取元素的时候可以用for循环遍历,也可以用Iterator,如果遍历过程中要增删改查,要用ListIterator;

        ListIteratorList集合特有的迭代器,是Iterator的子接口。

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

       ListIterator特有的方法

        add(obj);//增加

        set(obj);//修改为obj

        hasPrevious();//判断前面有没有元素

        previous();//取前一个元素

举例:

 

package one;

import java.util.*;
import java.util.Iterator;
import java.util.ListIterator;



public class ListDemo {
	//打印
	public static void sop(Object obj)
	{
		System.out.println(obj);
		
	}

	
	public static void main(String[] args) {
		// 新建一个容器
		ArrayList a1 = new ArrayList();
		//添加元素
		a1.add("java01");
		a1.add("java02");
		a1.add("java03");
		a1.add("java04");
		
		sop("原集合是:"+a1);
		
		//在指定位置添加元素;
		a1.add(2, "wanghuitao");
		
		//删除指定位置的元素;
		a1.remove(3);
		
		//修改角标获取元素。
		a1.set(0, "hahha");
		
		//获取所有元素,只要有角标,就可以用for循环遍历
		for(int i =0;i<a1.size();i++)
		{
			
			sop("a1("+i+")"+a1.get(i));
		}
	
		sop(a1.get(3));
		
		sop(a1);
		
		/*Iterator it = a1.iterator();
		while(it.hasNext())
		{
		Object obj=it.next();
		if(obj.equals("java02"))
			it.remove();
	
		}*/
		
		ListIterator li=a1.listIterator();
		while(li.hasNext())
		{
			Object obj=li.next();
			if(obj.equals("java02"))
			li.set("wode");
		}
		
		sop("迭代器遍历:"+a1);

	}

}


 

package one;

import java.util.*;



/*
 * 去除Arraylist集合中的重复元素;
 * */
public class ArrayListTest {
	//打印
	public static void sop(Object obj)
	{
		System.out.println(obj);
		
	}
	//去重
	
	public static ArrayList singleElement(ArrayList al)
	{
		//定义一个临时容器
	   ArrayList newAl = new ArrayList();
	   
	   Iterator it = al.iterator();
	   while(it.hasNext())
	   {
		  Object obj=it.next();
		  //用contains判断是否有重复元素,没有添加到新容器中;
		  if(!newAl.contains(obj))
			  newAl.add(obj);
	   }
	   return newAl;
	
		
	}
	public static void main(String args[])
	{
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java03");
		
		sop(singleElement(al));
		
		
		
		
		
		
	}
	


}

 

package one;

import java.util.*;



/*
 * 去除Arraylist集合中的重复元素;
 * */
public class ArrayListTest {
	//打印
	public static void sop(Object obj)
	{
		System.out.println(obj);
		
	}
	//去重
	
	public static ArrayList singleElement(ArrayList al)
	{
		//定义一个临时容器
	   ArrayList newAl = new ArrayList();
	   
	   Iterator it = al.iterator();
	   while(it.hasNext())
	   {
		  Object obj=it.next();
		  //用contains判断是否有重复元素,没有添加到新容器中;
		  if(!newAl.contains(obj))
			  newAl.add(obj);
	   }
	   return newAl;
	
		
	}
	public static void main(String args[])
	{
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java03");
		
		sop(singleElement(al));
		
		
		
		
		
		
	}
	


}

比较数组去重的方法:

public class QuChongyByArr {
 
       public static void main(String[] args) {
 
               int[] nums = { 4, 2, 4, 6, 1, 2, 4, 7, 8 };
 
              int[] newArr = new int[10];
 

 
               int flag = 0;//判断新数组是否存在相同的值
 
               int pos = 0;//新数组的角标
 
               for (int i = 0; i < nums.length; i++) {
 
                       for (int j = 0; j < newArr.length; j++) {// 判断nums[i]是否已在newArr中
 
                              if (nums[i] == newArr[j]) {
 
                            	 flag=1;
                            	 break;//跳出内层循环,已经相等,就没必要遍历newArr后面的数据;
                               }
                             
 
                       }
                       if(flag==1)
                    	   flag=0;
                       else
                       {
                    	   newArr[pos]=nums[i];
                    	   pos++;
                       }
 
                       
               }
                System.out.print("[");
 
                for (int i = 0; i < pos; i++) {
 
                        System.out.print(newArr[i] + ",");
 
                }
 
                System.out.println("]");
 

        }
}


 

package day05;

import java.util.ArrayList;
import java.util.Iterator;
/*
将自定义对象作为元素存到ArrayList集合里,去除除重复元素
*/
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;
	}
//复写object类中的object方法,给出比较标准,而基本数据类型已经覆盖过,所以不需要复写
	public boolean equals(Object obj) {
		if (!(obj instanceof Person))
			return false;
		else {
			Person p = (Person) obj;
			return this.getName() == p.getName() && this.getAge() == p.getAge();
		}

	}
}

public class ArrayListTest {
	public static ArrayList singleElement(ArrayList al) {
		// 定义一个临时容器
		ArrayList newAl = new ArrayList();

		Iterator it = al.iterator();
		while (it.hasNext()) {
			Object obj = it.next();
			if (!newAl.contains(obj))
				newAl.add(obj);
		}
		return newAl;

	}

	public static void main(String[] args) {

		ArrayList al = new ArrayList();
		al.add(new Person("lisi01", 23));
		al.add(new Person("lisi02", 23));
		al.add(new Person("lisi01", 34));
		al.add(new Person("lisi01", 23));
		al.add(new Person("lisi02", 23));

		
		ArrayList ab=singleElement(al);
		
		
		Iterator it =ab.iterator();
		while (it.hasNext()) {
			Person p = (Person) it.next();//使用子类特有方法,对象向下转型,
			System.out.println(p.getName() + "::" + p.getAge());
		}

	}

}


 

3.LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。

特有方法:

(1)

        addFirst();// 在头部添加

        addLast();//在尾部添加

(2)获取

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

        getFirst();

        getLast();

(3)

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

        removeFirst();

        removeLast();

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

(1)

        offFirst();

        offLast();

(2)获取

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

        peekFirst();

        peekLast();

(3)

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

        pollFirst();

        pollLast();

举例:

 

package one;

import java.util.LinkedList;
/*
使用linkList模拟一个堆栈或者队列数据结构;

堆栈:先进后出;
队列:先进先出;
*/

//模拟堆栈
class DuiLie
{
private LinkedList link;
 //初始化一个链表容器
DuiLie()
{
link=new LinkedList();	
}


public void myAdd(Object obj)
{
	//添加列表头部
link.addFirst(obj);	
}

//结果:先进后出
public Object myGet()
{
	
return link.removeFirst();

}
//结果:先进先出
public Object myGet_1()
{
	
	return link.removeLast();
}

public boolean isNull()
{
return link.isEmpty();	
}


}






public class LinkList {

	
	public static void main(String[] args) {
		
		DuiLie d = new DuiLie();
		d.myAdd("java01");
		d.myAdd("java02");
		d.myAdd("java03");
		d.myAdd("java04");
		
		System.out.println("模拟栈--先进后出");
		while(!d.isNull())
		{
			System.out.println(d.myGet());
			
		}
		
		/*队列:先进先出
		 * while(!d.isNull())
		{
			System.out.println(d.myGet_1());
			
		}*/
		

	}

}


 

四、Set集合

1. Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。   

           |--HashSet:底层数据结构是哈希表。线程不同步。保证元素唯一性的原理:判断元素的hashCode值是否相同。如果相同,还会继续判断元素的equals方法,是否为true

           |--TreeSet:可以对Set集合中的元素进行排序。默认按照字母的自然排序。底层数据结构是二叉树。保证元素唯一性的依据:compareTo方法return 0

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

2. HashSet:线程不安全,存取速度快。

       可以通过元素的两个方法,hashCodeequals来完成保证元素唯一性。如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashCode值不同,不会调用equals

注意:HashSet对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCodeequals方法。

举例:

 

package two;

import java.util.HashSet;
import java.util.Iterator;

/*
往hashSet集合中存入自定义对象,
姓名和年龄相同为同一个人,重复元素,去除重复元素
思路:
1.对人描述,将人的一些属性等封装进对象;
2.定义一个hashSet容器,存入对象
3.取出;

*/
class Person3
{
private String name;
private int age;

Person3(String name,int age)
{
this.name  = name;
this.age = age;
}

public String getName()
{
return name;	
}

public int getAge()
{
return age;	
}

public int hashCode()
{
	//return 20;
//按照条件设置hashcode值,字符串也有自己的哈希值,字符串对象有自己的hashcode方法,这样可以减少比较的次数。
	//乘以4是为了避免那个对象的名字跟hashcode组合碰巧和相等
	return this.name.hashCode()+age*4;	
}

public boolean equals(Object obj)
{
if(!(obj instanceof Person3))
	return false;
else
{
Person3 p = (Person3)obj;
//System.out.println(this.name+"...."+p.name);
return this.name.equals(p.name)&&this.age==p.age;
}
}


}

public class HashSetDemo {

	
	public static void main(String[] args) {
		
		HashSet hs = new HashSet();
		hs.add(new Person3("a1",11));
		hs.add(new Person3("a2",12));
		hs.add(new Person3("a3",13));
		hs.add(new Person3("a2",12));
		
		System.out.println(hs.remove(new Person3("a3",13)));
		Iterator it = hs.iterator();
		while(it.hasNext())
		{
			Person3 p = (Person3)it.next();
			System.out.println(p.getName()+"....."+p.getAge());
		}
		
		
		System.out.println("a1:"+hs.contains(new Person3("a1",11)));
		

		
	}

}


 

3.TreeSet特点

       a、底层的数据结构为二叉树结构(红黑树结构)

        b、可对Set集合中的元素进行排序,是因为:TreeSet类实现了Comparable接口,该接口强制让增加到集合中的对象进行了比较,需要复写compareTo方法,才能让对象按指定需求(如人的年龄大小比较等)进行排序,并加入集合。

        java中的很多类都具备比较性,其实就是实现了Comparable接口。

注意:排序时,当主要条件相同时,按次要条件排序。

       c、保证数据的唯一性的依据:通过compareTo方法的返回值,是正整数、负整数或零,则两个对象较大、较小或相同。相等时则不会存入。

*****Tree排序的两种方式

(1)第一种排序方式:自然排序

让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方式也被称为元素的自然顺序,或者叫做默认顺序。

举例:

 

package day05;

import java.util.*;
//学生类
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;
	}
	
	//复写compareTo以便TreeSet集合调用
	public int compareTo(Object obj)
	{
		Student s=(Student)obj;
		if(this.age==s.age)
			return this.name.compareTo(s.name);
		return this.age-s.age;
		//return new Integer(this.age).compareTo(new Integer(s.age)); 
	}
}

public class TreeSetTest
{
	public static void main(String[] args) 
	{
		TreeSet<Student> t=new TreeSet<Student>();
		t.add(new Student("lisi1",12));
		t.add(new Student("abd",2));
		t.add(new Student("do",19));
		t.add(new Student("od",19));
		

		Iterator<Student> it=t.iterator();
		while(it.hasNext())
		{
			Student s=it.next();
			System.out.println(s.getName()+"....."+s.getAge());
		}
	}
}


 

(2)第二种方式:比较器

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

  在集合初始化时,就有了比较方式。定义一个比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。

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

   当两种排序都存在时,以比较器为主。

举例:

 

package two;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;


class Student2
{
private String name;
private int age;

Student2(String name,int age)
{
this.name=name;
this.age=age;
}

public String getName(){
	return name;
	
}

public int getAge(){
	return age;
}
}

//定义比较器,先按姓名的自然排序,再排年龄
class MyCompare implements Comparator
{
public int compare(Object o1,Object o2)
{
Student2 s1= (Student2)o1;
Student2 s2=(Student2)o2;

int num=s1.getName().compareTo(s2.getName());
if(num==0)
{
return new Integer(s1.getAge()).compareTo(s2.getAge());	
}
return num;


}
}

public class TreeSetDemo2 {

	
	public static void main(String[] args) {
		
		TreeSet ts = new TreeSet(new MyCompare());
		
		
		ts.add(new Student2("lisi02",22));
		ts.add(new Student2("lisi007",20));
		ts.add(new Student2("lisi09",19));
		ts.add(new Student2("lisi06",18));
		ts.add(new Student2("lisi007",26));
		
		Iterator it = ts.iterator();
		while(it.hasNext())
		{
			Student2 stu = (Student2)it.next();
			System.out.println(stu.getName()+"...."+stu.getAge());
		}
		
		
		
		
	}

}


 

五、Map

1.简述

Map<K,V>集合是一个接口,和List集合及Set集合不同的是,它是双列集合,并且可以给对象加上名字,即键(Key

2特点:

        1)该集合存储键值对,一对一对往里存

        2)要保证键的唯一性。

3.map集合的框架

   Map

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

            |--HashMap:底层是哈希表数据结构。允许使用nullnull值,该集合是不同步的。JDK1.2,效率高。

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

        MapSet很像。其实Set底层就是使用了Map集合。

4.Map常用方法

(1)添加

        put(K key,V value);//添加元素,如果出现添加时,相同的键,那么后添加的值会覆盖原有键对应值,并put方法会返回被覆盖的值。

        voidputAll(Map <? extends K,? extends V> m);//添加一个集合

(2)删除

        clear();//清空

        Vremove(Object key);//删除指定键值对

(3)判断

        containsKey(Objectkey);//判断键是否存在

        containsValue(Objectvalue)//判断值是否存在

        isEmpty();//判断是否为空

(4)获取

        get(Object key);//通过键获取对应的值

        size();//获取集合的长度

        Collection<V>value();//获取Map集合中所以得值,返回一个Collection集合

还有两个取出方法,接下来会逐个讲解:

        Set<Map.Entry<K,V>>entrySet();

        Set<K>  keySet();

注:HashMap集合可以通过get()方法的返回值来判断一个键是否存在,通过返回null来判断。

5.Map集合的两种取出方式

        Map集合的取出原理:将Map集合转成Set集合。再通过迭代器取出。

1Set<K> keySet():将Map中所以的键存入到Set集合。因为Set具备迭代器。所以可以通过迭代方式取出所以键的值,再通过get方法。获取每一个键对应的值。

如图:

 

 

package day05;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class MapDemo {

	
	public static void main(String[] args) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("02", "zhangsan1");
		map.put("03", "zhangsan2");
		map.put("01", "zhangsan3");
		map.put("02", "zhangsan1");
		
		//先获取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);
		}
		
	}

}


 

2Set<Map.Entry<K,V>>   entrySet():将Map集合中的映射关系存入到Set集合中,而这个关系的数据类型就是:Map.Entry

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

 

interface Map {
	public static interface Entry {
		public abstract Object getKey();

		public abstract Object getValue();

	}
}

class HashMap implements Map {
class Ha implements Map.Entry{
	public Object getKey(){}
	public Object getValue(){}
}

}


 

package day05;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class MapDemo {

	
	public static void main(String[] args) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("02", "zhangsan1");
		map.put("03", "zhangsan2");
		map.put("01", "zhangsan3");
		map.put("02", "zhangsan1");
		
		/*//先获取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集合中的映射关系取出,存入到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:"+key+",value:"+value);
		}
		
	}

}


 

注意: Map是一个接口,其实,Entry也是一个接口,它是Map的子接口中的一个内部接口,就相当于是类中有内部类一样。为何要定义在其内部呢?

原因:aMap集合中村的是映射关系这样的两个数据,是先有Map这个集合,才可有映射关系的存在,而且此类关系是集合 的内部事务。

            b、并且这个映射关系可以直接访问Map集合中的内部成员,所以定义在内部。

 Map集合的练习题:

练习1

package xin;


import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/*
 *每个学生都有对应的归属地
 *学生student, 地址String
 *学生属性:姓名,年龄;
 *注意:姓名和年龄相同的视为同一个学生。
 *保证学生的唯一性。
 *
 *思路:
 *1.描述学生类
 *2.定义一个map集合,存储学生对象和地址值
 *3.获取map中的元素

*/

//.描述学生类
class Student1 implements Comparable<Student1>
{
	//描述学生属性
	private String name;
	private int age;
	//学生初始化
	Student1(String name,int age)
	{
	this.name = name;
	this.age=age;
	}
	//获得学生姓名
	public String getName()
	{
		return name;
	}
	//设置学生姓名
	public int getAge()
	{
		return age;
	}
	//复写hashcode方法
	public int hashCode()
	{
		return name.hashCode()+age*3;
	}
	//复写equals方法
	public boolean equals(Object obj)
	{
		if(obj instanceof Student1)
			return false;
		Student1 s =(Student1)obj;
		return this.name==s.name&&this.age==s.age;
		
	}

	//先按年龄排序,再按姓名排序
	public int compareTo(Student1 s) {
		int num=new Integer(this.age).compareTo(s.age);
		if(num==0)
			return this.name.compareTo(s.name);
		return num;
		
	}
	//复写tostring()方法
	public String toString()
	{
		
		return name+":"+age;
	}
	
}

public class MapTest {

	
	public static void main(String[] args) {
		//定义一个hashMap集合
		HashMap<Student1,String> hm = new HashMap<Student1,String>();
		//添加学生对象和地址值
		hm.put(new Student1("lisi1",21), "beijing");
		hm.put(new Student1("lisi2",22), "shangai");
		hm.put(new Student1("lisi3",23), "wuhan");
		hm.put(new Student1("lisi4",24), "nanjing");
		
		//第一种取出方式;keyset,先取出所有键的值
		Set<Student1> keySet = hm.keySet();
		//获得迭代器
		Iterator<Student1> it = keySet.iterator();
		while(it.hasNext())
		{
			//迭代器去下一个元素
			Student1 stu=it.next();
			//通过集合的get方法获取vlaue值
			String addr = hm.get(stu);
			System.out.println(stu+"......"+addr);
			
		}
		
		
		//第二种:entrySet
		//先取出映射关系集合
		Set<Map.Entry<Student1, String>> entrySet =hm.entrySet();
		//获取迭代器
		Iterator<Map.Entry<Student1, String>> iter = entrySet.iterator();
		while(iter.hasNext())
		{
			 //取下一个映射关系
			Map.Entry<Student1, String> me = iter.next();
			//通过映射关系集合的get方法获取键和值
			Student1 stu=me.getKey();
			String addr=me.getValue();
			
			System.out.println(stu+"----"+addr);
		}
		
		
		

	}

}


练习2:

package xin;



import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;


/*
获取字符串中的字母出现的次数,
分析:每个字母都有次数,说明字母和次数之间有映射关系。
*/
public class MapTest3 {
	
	public static void charCount(String str)
	{
		//将字符串转化为字符数组
		char[] chs =str.toCharArray();
		//定义一个TreeMap集合用于存储字母和字母出现的次数,TreeMap集合会给字母自动排序
		TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
		//遍历数组
		for(int i =0;i<chs.length;i++)
		{
			// 获取键值
			Integer value = tm.get(chs[i]);
			// 如果键值为空,键值置为1
			if(value==null)
			{
				tm.put(chs[i], 1);
				
			}
			// 否则,键值加1,存入集合
			else
			{
				value = value+1;
				tm.put(chs[i], value);
			}
			
		}
		//System.out.println(tm);
		//建立缓冲区
		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();
			System.out.print(ch+"("+value+")");
			
		}

	

		
	}

	
	public static void main(String[] args) {
		charCount("ackidid");
		
	}

}

 练习3

package xin;


import java.util.*;
/*在很多项目中,引用比较多的是一对多的映射关系,这就可以通过嵌套的形式将多个映射定义到一个大的集合中,并将大的集合分级处理,形成一个体系。


班级对应学生,学生类中学号对应姓名
“yure” Student("01","zhangdan")
“yure” Student("02","lisi")

“jiuye” Student("01","wangwu")
“yure” Student("02","zhaojiu")
如同一个学校有多个教室,每个教室都有名称;
**/

//描述学生类
class Student {
	//学生属性
	String id, name;
	//初始化
	Student(String id, String name) {
		this.name = name;
		this.id = id;
	}
//自定义tostring方法
	public String toString() {

		return id + "::" + name;
	}
}

public class MapDemo {

	public static void main(String[] args) {

		//建立czbk的结合
		Map<String, ArrayList<Student>> czbk = new HashMap<String, ArrayList<Student>>();
		//建立班级集合,一个jiuye,一个yure
		ArrayList<Student> yure = new ArrayList<Student>();
		ArrayList<Student> jiuye = new ArrayList<Student>();
		//添加班级实体
		czbk.put("yureban", yure);
		czbk.put("jiuyeban", jiuye);
		//班级实体添加学生
		yure.add(new Student("01", "zhangsan"));
		yure.add(new Student("02", "lisi"));

		jiuye.add(new Student("01", "wnagwu"));
		jiuye.add(new Student("02", "zhaoliu"));

		//获取迭代器,获得锁有房间名
		Iterator<String> it1 = czbk.keySet().iterator();
		while (it1.hasNext()) {
			String roomname = it1.next();
			System.out.println(roomname);
			ArrayList<Student> al = czbk.get(roomname);
			//获取迭代器,遍历学生对象
			Iterator<Student> it2 = al.iterator();
			while (it2.hasNext()) {
				//通过迭代器获取每一个学生对象
				Student w = (Student) it2.next();
				//打印
				System.out.println(w.toString());
			}
		}

	}

}

	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	



关于集合的总结:

集合总结:

集合的一些技巧:

需要唯一吗?
需要:Set
需要制定顺序:
需要: TreeSet
不需要:HashSet
但是想要一个和存储一致的顺序(有序):LinkedHashSet
不需要:List
需要频繁增删吗?
需要:LinkedList
不需要:ArrayList
如何记录每一个容器的结构和所属体系呢?
看名字!
List
|--ArrayList
|--LinkedList
Set
|--HashSet
|--TreeSet
后缀名就是该集合所属的体系。
前缀名就是该集合的数据结构。
看到array:就要想到数组,就要想到查询快,有角标.
看到link:就要想到链表,就要想到增删快,就要想要 add get remove+frist last的方法
看到hash:就要想到哈希表,就要想到唯一性,就要想到元素需要覆盖hashcode方法和equals方法。
看到tree:就要想到二叉树,就要想要排序,就要想到两个接口Comparable,Comparator 。
而且通常这些常用的集合容器都是不同步的


Map:一次添加一对元素。Collection 一次添加一个元素。
Map也称为双列集合,Collection集合称为单列集合。
其实map集合中存储的就是键值对。
map集合中必须保证键的唯一性。

 

积分:120

1.枚举:让某个类型的变量的取值只能为若干个固定值中的一个。

2.特点:(1)枚举类是一个特殊的类,每个元素都是该类的一个实例对象,用enum关键字定义枚举类;

              (2)枚举类型继承过java.lang.Enum类

               (3)枚举类没有public的构造函数

               (4)枚举值是public statiche final的

举例:

package day09;

//定义枚举类,
enum Color
{
red,green,blue;	
}
 //定义花
class Flower
{
private String name;
Color color;
public Flower(String name, Color color) {
	super();
	this.name = name;
	this.color = color;
}
@Override
public String toString() {
	return "Flower [name=" + name + ", color=" + color + "]";
}


}
public class EnumDemo {

	
	public static void main(String[] args) {
		
		Flower f = new Flower("moli",Color.red);
		System.out.println(f);

	}




}

二、静态导入

可以使被导入的静态变量和静态方法在当前类直接可见,使用这些静态成员无需再给出它们的类名

例如:import staticjava.util.Arrays.*;

注意:当类名重名时,需要指定具体的包名。

当方法重名时,指定具备所属的对象或者类。

三、增强for循环

1.格式:for(数据类型变量名 :被遍历的集合(collection)或者数组) {执行语句}

2 .注意:对集合进行遍历。只能获取集合元素。但是不能对集合进行操作。可以看作是迭代器的简写形式

3 .传统for和高级for的区别:

    高级for有一个局限性。必须有被遍历的目标(集合或数组)。

    传统for遍历数组时有索引。

    建议在遍历数组的时候,还是希望使用传统for。因为传统for可以定义角标。

举例:

package day09;

import java.util.*;
public class ForDemo
{
	public static void main(String[] args) 
	{
		//定义一个ArrayList集合
		ArrayList<String> al = new ArrayList<String>();
		al.add("lisi1");
		al.add("lisi2");
		al.add("lisi3");
		//用增强for遍历集合
		for(String s : al)
		{
			System.out.println(s);
		}

		//传统for与 增强for区别
		int[] arr = {23,2,5,4};

		for(int i=0; i<arr.length; i++)
		{
			System.out.println(arr[i]);
		}
		for(int i : arr)
		{
			System.out.println("i:"+i);
		}

		

	}
}
四 、可变参数

1.如果一个方法在参数列表中传入多个参数,个数不确定,那么每次都要复写该方法。这时可以用数组作为形式参数。但是在传入时,每次都需要定义一个数组对象,作为实际参数。在JDK1.5版本后,就提供了一个新特性:可变参数。

2.  用…这三个点表示,且这三个点位于变量类型和变量名之间,前后有无空格皆可。

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

在使用时注意:可变参数一定要定义在参数列表的最后面。

举例:

package day09;

import java.util.*;

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

		show(3, 4, 5,6,5,4,3);
	}

	private static void show(int ...a) {
		for(int i = 0; i<a.length;i++){
			System.out.print(a[i]+" ");
		}

	}

}

五、基本数据类型的自动拆箱与装箱

1.自动装箱,拆箱

Integer  x = new Integer(5);

等价于:Integer x = 5;//自动装箱,new Integer;

x = x+2;//x进行自动拆箱,变成了int类型,和2运算,再将和进行装箱赋给x

注意:对于基本数据类型的说明:整数在-128 ~ 127之间的数,包装成Integer类型对象,会存入常量池中的缓存,再创建一个对象的时候,如果其值在这个范围内,就会直接到常量池中寻找,因为这些小数值使用的频率很高,所以缓存到常量池中,被调用时就方便很多。

 

 六 泛型:

泛型:
jdk1.5出现的安全机制。
好处:
1,将运行时期的问题ClassCastException转到了编译时期。
2,避免了强制转换的麻烦。
<>:什么时候用?当操作的引用数据类型不确定的时候。就使用<>。将要操作的引用数据类型传入即可.
其实<>就是一个用于接收具体引用数据类型的参数范围。
在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型 。
泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。
运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为泛型的擦除。
为什么擦除呢?因为为了兼容运行的类加载器。

泛型的补偿:在运行时,通过获取元素的类型进行转换动作。不用使用者在强制转换了。
泛型的通配符:? 未知类型。
泛型的限定:
? extends E: 接收E类型或者E的子类型对象。上限
一般存储对象的时候用。比如 添加元素 addAll.
? super E: 接收E类型或者E的父类型对象。 下限。
一般取出对象的时候用。比如比较器。




 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值