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

黑马程序员-Java的集合类(java中类的容器)和算法

2015-12-13 15:08 585 查看
                     -----------android培训、java培训、java学习型技术博客、期待与您交流!------------

                                       Java的集合类(java中类的容器)和算法

一、集合

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

   

    2、java的数据结构:每一个容器对数据的存储方式不同,所以具有多种多样的容器;

   

    3、集合中的分类和常用接口、类

 |--Collection集合接口:一组单独的元素存储

  |--List列表接口:元素是有序的(存入和取出的顺序一致),元素都有索引(角标),元素允许重复。

   |--ArrayList:底层数据结构是数组,查询速度快,增删操作较慢,线程不同步

   |--LinkedList:底层数据结构是链表,查询效率较低,增删操作快,线程不同步

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

  |--Set集接口:元素是无序的(存入和取出的顺序不一定一致),元素不允许重复,底层用到了Map

   |--HashSet:底层数据结构是哈希表,存储的对象最好复写hashCode和equals方法,保证元素不会重复。线程不同步。

   |--TreeSet:底层数据结构是二叉树,可以对Set集合中的元素按自然顺序进行排序,线程是不同步的。

               存储的对象具备比较性。

 |--Map映射接口:数据是以键值对的形式存储的,有的元素存在映射关系就可以使用该集合,元素不允许重复

  |--HashTable:底层数据结构是哈希表,线程同步。不允许有null键或值。jdk1.0效率低;

  |--HashMap:底层数据结构也是哈希表,线程不同步。允许有null键或值。将hashtable替代,jdk1.2效率高。 

  |--TreeMap:底层数据结构是二叉树(红-黑树)。线程不同步。可通过比较器用于给Map集合中键进行排序。

     3、集合关系图

 

     


     4、集合的特点

        a、集合中存储的都是对象的引用(地址)。

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

二、Collection集合接口

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

        Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。

       一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。

    2、Collection的常见方法:

       a、添加:

  boolean add(Object obj);

  boolean addAll(Collection coll);

       b、删除:

  boolean remove(Object obj);

  boolean removeAll(Collection coll);

  void clear();

       c、判断:

  boolean contains(Object obj);

  boolean containsAll(Collection coll);

  boolean isEmpty();判断集合中是否有元素。

       d、获取:

  int size();

  iterator();

       e、其他:

                boolean removeAll(Collection<?> c);取差集

  boolean retainAll(Collection coll);取交集

  Object toArray();将集合转成数组

     

三、迭代器:

    1、集合是继承了public interface Iterable<T>接口的Iterator<T> iterator()方法。

    2、迭代器是集合的取出元素方式,会直接访问集合中的元素,所以将迭代器通过内部类的形式来进行描述。

           该对象必须依赖于具体容器,因为每一个容器的数据结构都不同,所以该迭代器对象是在容器中进行

       内部实现的,也就是iterator方法在每个容器中的实现方式是不同的。

      

       对于使用容器者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器的对象即可,也就是iterator方法。

    3、Iterator接口

  Iterator     iterator();

       a、Iterator接口就是对所有的Collection容器进行元素取出的公共接口。

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

       b、操作方法

  boolean hasNext();

  E next();

  void remove();

       注:在迭代循环中next()一次,就必须hasNext()判断一次;连续两次调用next()可能发生错误。

      

import  java.util.*;

class CollectionDemo {
public static void  collectionBaseOperater(){
Collection  a  =  new ArrayList();
//增加
a.add("java 01");
a.add("java 02");
a.add("java 03");
a.add("java 04");

//删除
a.remove("java 03");
//a.clear();

//长度
sop("a.size():"+a.size());

//是否为空
sop("a.contains:"+a.contains("java 03"));
sop("a.isEmpty:"+a.isEmpty());

//打印
sop(a);

sop("\r\n------------------------------\r\n");

//集合操作
Collection  a1  =  new ArrayList();
a1.add("java 01");
a1.add("java 02");
a1.add("java 03");
a1.add("java 04");

Collection  a2  =  new ArrayList();
a2.add("java 01");
a2.add("java 02");
a2.add("java 05");
a2.add("java 06");

//a1.retainAll(a2);//取交集
a1.removeAll(a2);//取差集

sop(a1);
sop(a2);
}

public static void printf(Collection c){

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

while(it.hasNext())
{
sop(it.next());
}
*/

//采用for循环,使it成为局部变量,用完就可以清除出内存,同时对象垃圾也可以回收。
for(Iterator  it = c.iterator();it.hasNext();){
System.out.print(it.next()+" ");
}
System.out.println();
}

public static void main(String[] args) {

//collectionBaseOperater();

String[] strArr = {"This","is ","a","java","test."};
Collection  a  =  new ArrayList();
for(int i=0;i<strArr.length;i++){
a.add(strArr[i]);
}

printf(a);
}

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


 

    4、ListIterator类

       a、ListIterator是Iterator的子接口。

              在迭代操作时,不可以又通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常。

   所以,在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,

   如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。该接口只能通过List集合的listIterator方法获取。

       b、系列表迭代器,允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。

          只能用于List及其子类型。

       c、操作方法

  void add(E e);

  boolean hasNext();

  E next();//覆盖了Iterator接口的方法

  void remove();

               

  //逆向遍历,从集合的最后一个元素读取,判断前面有没有元素

  boolean hasPrevious();//第一次使用的是时候为假,如果接着previous,就会发生NoSuchElementException违例,

                        //所以要先判断,再使用previous();

  E previous();

    

四、List列表接口及其相关类

    1、List的共性方法:特有的常见方法,有一个共性特点就是都可以操作角标。

       a、添加(插入)

  void add(int index,E element);

  boolean addAll(int index,Collection<? extends E> c);

       b、删除

  E remove(int index);

  boolean remove(Object o);

       c、修改

  E set(int index,E element);

       d、获取:

  E get(int index);

  int indexOf(Object o);

  int lastIndexOf(Object o);//获取指定元素的位置。

  List<E> subList(int fromIndex,int toIndex);

  ListIterator listIterator();

    2、ArrayList类*

       (1)动态数组的数据结构,默认长度为10,当超过时50%延长,而Vector是100%延长。

       (2)ArrayList类与List接口中方法基本一致。

       (3)ArrayList和LinkedList的大致区别:

           a、ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。

           b、对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。

           c、对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据

       

import java.util.*;

class ListDemo {

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

public static void printf(Collection c){
for(Iterator  it = c.iterator();it.hasNext();){
System.out.print(it.next()+" ");
}
System.out.println();
}

public  static void listBaseOperator(List ls){
ls.add(2,"abc6");
sop(ls);

//ls.remove(2);
//sop(ls);

ls.set(2,"abc8");
sop(ls);

for(int i=0;i<ls.size();i++){
System.out.println("ls["+i+"]="+ls.get(i));
}

printf(ls);

ls.add(3,"abc6");
ls.add(2,"abc2");
printf(ls);
int index1 = ls.indexOf("abc2");
int index2 = ls.lastIndexOf("abc2");
System.out.println("index1="+index1+","+"index2="+index2);

List subLs = ls.subList(1,3);
printf(subLs);
}

public static void listIteratorOperator(List ls){
/*

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);
*/

ListIterator li = ls.listIterator();

sop("hasPrevious():"+li.hasPrevious());//hasPrevious():false
//sop("pre::"+li.previous());//Exception in thread "main" java.util.NoSuchElementException

while(li.hasNext())
{
Object obj = li.next();
if(obj.equals("abc2"))
//li.add("java009");
li.set("abc6");
}

while(li.hasPrevious())
{
sop("pre::"+li.previous());
}

/*
结果:
pre::abc6
pre::abc1
pre::abc0
*/

sop("hasNext():"+li.hasNext());//hasNext():false,取到了最后,指针后面没有元素了。
sop("hasPrevious():"+li.hasPrevious());//hasPrevious():true

sop(ls);
}

public static void main(String[] args) {
String[] strArr = {"abc0","abc1","abc2"};
List  ls  =  new ArrayList();
for(int i=0;i<strArr.length;i++){
ls.add(strArr[i]);
}

sop(ls);

//listBaseOperator(ls);

listIteratorOperator(ls);
}
}


  

import java.util.*;

class ArrayListTest1 {

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

public static List removeRepeatElement(List li){
List  newArr =  new ArrayList();
//for(int i =0;i<li.size();i++){
//Object obj = li.get(i);
//if(!newArr.contains(obj)){
//newArr.add(obj);
//}
//}

for(Iterator it = li.iterator();it.hasNext();){
Object obj = it.next();
if(!newArr.contains(obj)){//调用存储对象的equals()方法判断。
newArr.add(obj);
}
}

return newArr;
}

public static void main(String[] args) {

List li =  new ArrayList();
li.add("abc0");
li.add("abc1");
li.add("abc2");
li.add("abc3");
li.add("abc1");

sop(li);
sop(removeRepeatElement(li));
}
}


 

    3、LinkedList类*

       特有方法:

       a、增加:

  public void addFirst(E e);

  public void addLast(E e);

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

  public boolean offerFirst(E e);//与addFirst方法没有区别

  public boolean offerLast(E e);//与addLast方法没有区别

       b、获取

  public E getFirst();

  public E getLast();

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

         

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

  public E peekFirst();

  public E peekLast();

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

       c、获取删除

  public E removeFirst();

  public E removeLast();

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

       

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

  public E pollFirst();

  public E pollLast();

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

      注:这里不能定义成List的引用,因为这些方法在List接口中都没有,是LinkedList类的特有方法。

    

    

import  java.util.*;

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

public static void printf(Collection c){
for(Iterator  it = c.iterator();it.hasNext();){
System.out.print(it.next()+" ");
}
System.out.println();
}

public static void main(String[] args) {
LinkedList  link = new  LinkedList();//这里不能定义成List的引用,因为这些方法在List接口中都没有,是LinkedList类的特有方法

link.offerFirst("abc0");
link.offerFirst("abc1");
link.offerFirst("abc2");
link.offerFirst("abc3");

sop(link);

//sop(link.peekFirst());
//sop(link);
//sop(link.peekFirst());
//sop(link);

//sop(link.pollFirst());
//sop(link);
//sop(link.pollFirst());
//sop(link);

//sop(link.peekLast());
//sop(link);

//sop(link.pollLast());
//sop(link);
printf(link);

while(!link.isEmpty()){
sop(link.pollLast());
}

printf(link);
}
}


   

/*
需求:使用LinkedList模拟一个堆栈或者队列数据结构。

分析:
堆栈:先进后出
队列:先进先出
*/

import java.util.*;

class MyStack{
private  LinkedList link;

MyStack(){
link = new  LinkedList();
}

public void setData(Object o){
link.offerFirst(o);
}

public  Object  getData(){
return link.pollFirst();
}

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

class MyQueue{
private  LinkedList link;

MyQueue(){
link = new  LinkedList();
}

public void setData(Object o){
link.offerFirst(o);
}

public  Object  getData(){
return link.pollLast();
}

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

class  LinkedListTest{

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

public static void main(String[] args) {
MyQueue  mq =  new MyQueue();

mq.setData("abc01");
mq.setData("abc02");
mq.setData("abc03");

sop(mq.getData());

MyStack  ms  =  new   MyStack();

ms.setData("def01");
ms.setData("def02");
ms.setData("def03");

sop(ms.getData());
}
}


 

     4、List集合中用contians()判断元素是否相同,依据是元素的equals方法。

        remove方法底层也是依赖于元素的equals方法。

       

/*
将自定义对象作为元素存到ArrayList集合中,并去除重复元素。
比如:存人对象。同姓名同年龄,视为同一个人。为重复元素。

思路:
1,对人描述,将数据封装进人对象。
2,定义容器,将人存入。
3,取出。

结论:List集合判断元素是否相同,依据是元素的equals方法;
remove方法底层也是依赖于元素的equals方法。
*/

import java.util.*;

class Person{
private String name;
private int age;
Person(String name,int age){
this.name = name;
this.age = age;
}

public boolean equals(Object obj){

if(!(obj instanceof Person))
return false;

Person p = (Person)obj;
//System.out.println(this.name+"....."+p.name);

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

public void setName(String name){
this.name = name;
}

public String getName(){
return name;
}

public void setAge(int age){
this.age = age;
}

public int getAge(){
return age;
}
}

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

public static ArrayList singleElement(ArrayList al)
{
ArrayList newArr = new ArrayList();
Iterator it = al.iterator();
while(it.hasNext())
{
Object obj = it.next();

if(!newArr.contains(obj))
newArr.add(obj);
}
return newArr;
}

public static void main(String[] args)
{
ArrayList al = new ArrayList();
al.add(new Person("lisi01",30));//al.add(Object obj);//Object obj = new Person("lisi01",30);
//al.add(new Person("lisi02",32));
al.add(new Person("lisi02",32));
al.add(new Person("lisi04",35));
al.add(new Person("lisi03",33));
//al.add(new Person("lisi04",35));

//al = singleElement(al);

sop("remove 03 :"+al.remove(new Person("lisi03",33)));。

Iterator it = al.iterator();
while(it.hasNext())
{
Person p = (Person)it.next();
sop(p.getName()+"::"+p.getAge());
}
}

}


 

五、Set集接口及其相关类

    1、Set的共性方法

       Set接口中的方法和Collection基本一致。

    2、HashSet类*

       HashSet保证元素唯一性:通过元素的两个方法,hashCode()和equals()方法来完成。

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

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

        注意:(1)对于自定义类的存放到HashSet中元素,需要覆盖hashCode和equals方法。

             (2)对于判断元素是否存在,以及删除等操作,依赖的方法是先通过hashCode()比较元素的hashcode值是否相同,

           如果相同,再继续判断元素的equals方法,是否为true。

     

import  java.util.*;

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是处理name和age不同,但是相加值相同的情况
}

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 void setName(String name){
this.name = name;
}

public String getName(){
return name;
}

public void setAge(int age){
this.age = age;
}

public int getAge(){
return age;
}
}

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));

//sop("a1:"+hs.contains(new Person("a2",12)));

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

for(Iterator it = hs.iterator();it.hasNext();)
{
Person p = (Person)it.next();
sop(p.getName()+"::"+p.getAge());
}
}
}


      

      

    3、TreeSet类

       a、在TreeSet集合中存储的对象对应的类必须继承Comparable接口,告诉它排序的方法;否则没有办法存储,编译不能通过。

       b、TreeSet判断元素唯一性的依据:

          在集合初始化时,就有了比较方式。就是根据比较compareTo方法的返回结果是否是0,是0,就是相同元素,不存储。

       c、TreeSet集合的底层是二叉树进行排序的

          TreeSet排序的第一种方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法(当主要条件相同时,需要比较次要条件)。

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

     

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

//return 0; 在集合初始化时,就有了比较方式。就是根据比较compareTo方法的返回结果是否是0,是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 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));

for(Iterator it = ts.iterator();it.hasNext();){
Student stu = (Student)it.next();
System.out.println(stu.getName()+"..."+stu.getAge());
}
}
}


 

   TreeSet的第二种排序方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。

                           

                                   让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。

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

                                   当两种排序都存在时,以比较器为主。定义一个类,实现Comparator接口,覆盖compare方法。

       如果自定义类实现了Comparable接口,并且TreeSet的构造函数中也传入了比较器,那么将以比较器

                                   的比较规则为准。

    

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 int compareTo(Object obj){
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(new MyComparator());

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

for(Iterator it = ts.iterator();it.hasNext();){
Student stu = (Student)it.next();
System.out.println(stu.getName()+"..."+stu.getAge());
}
}
}

class  MyComparator 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){//排序时,当主要条件相同时,一定判断一下次要条件。
}

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;
}
}


                               

       注:不管是在覆盖compareTo方法时,还是覆盖compare方法;当主要条件相同时,需要比较次要条件。

 

 

/*
需求:按照字符串长度排序。
*/

import java.util.*;

class TreeSetTest {
public static void main(String[] args){
TreeSet ts = new TreeSet(new MyComparator());

ts.add("abcde");
ts.add("cd");
ts.add("bc");
ts.add("dte");
ts.add("iop");

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

class  MyComparator 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;
}
}


      

七、Map映射接口及其相关类

    1、Map<K,V>集合:

       (1) 将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

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

 例如:地图上,经纬度和图片地点之间就是典型的Map关系。

       (2)Map的键是一个HashSet的集合。

     注:Map和Set很像,其实Set底层就是使用了Map集合。

    2、Map的共性方法

 a、添加:如果添加元素时,出现相同的键。那么后添加的值会覆盖原有键对应值,并put方法会返回被覆盖的值。

  V put(K key,V value);

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

 b、删除

  void clear();

  V remove(Object key);

 c、判断

  boolean containsKey(Object key);

  boolean containsValue(Object value);

  boolean isEmpty();

 d、获取

  int size();

  V get(Object key);//可以通过get方法的返回值来判断一个键是否存在。通过返回null来判断。

  

  Collection<V> values(); //获取map集合中所有的值。

  Set<K> keySet();

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

      

import  java.util.*;

class  MapDemo{
public static void main(String[] args) {
Map<String,String>   map = new  HashMap<String,String>();

System.out.println(map.put("100","abc00"));
map.put("101","abc0");
map.put("102","abc1");
map.put("103","abc2");
map.put("104","abc3");
map.put("105","abc4");
System.out.println(map.put("105","abc5"));

System.out.println("map.containKey:"+map.containsKey("102"));
//System.out.println("map.remove:"+map.remove("102"));

map.put(null,"abc6");
System.out.println("get(null):"+map.get(null));
map.put("106",null);
System.out.println("get:"+map.get("106"));

Collection<String>  cl  =  map.values();
System.out.println(cl);

System.out.println(map);
}
}


 

     3、map集合的两种取出方式:

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

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

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

       (2)Set<Map.Entry<k,v>> entrySet()方法:

            a、将map集合中的映射关系存入到了set集合中,即Map.Entry对象。

    

     b、而这个关系的数据类型就是:Map.Entry。Entry其实就是Map中的一个static内部接口。

        定义在内部因为只有有了Map集合,有了键值对,才会有键值的映射关系。关系属于Map集合中的一个内部事物。

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

     c、Map.Entry内部类有方法

   K getKey();

   V getValue();

              其实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(){}

    } 

   }

             注:可以看做在HashMap和TreeMap类内部实现了Entry类,把Key和Value合并成一个特殊形式的字符串,加以保存。

     

import  java.util.*;

class  MapDemo2{
public static void readMethodByKey(Map map){
Set<String>  set = map.keySet();
for(Iterator<String>  it = set.iterator();it.hasNext();){
String key  =  it.next();

String values = (String)map.get(key);

System.out.println("key= "+key+"->"+"values= "+values);
}
}

public static void readMethodByEntry(Map map){
Set<Map.Entry<String,String>>  entry  = map.entrySet();

//for(Iterator  it = entry.iterator();it.hasNext();){
//Map.Entry<String,String> mapEntry = (Map.Entry<String,String>)it.next();
for(Iterator<Map.Entry<String,String>>  it = entry.iterator();it.hasNext();){
Map.Entry<String,String> mapEntry = it.next();

String key  = mapEntry.getKey();
String values = mapEntry.getValue();

System.out.println("key= "+key+"->"+"values= "+values);
}

}

public static void main(String[] args) {
Map<String,String>   map = new  HashMap<String,String>();

map.put("101","abc0");
map.put("102","abc1");
map.put("103","abc2");
map.put("104","abc3");
map.put("105","abc4");

readMethodByKey(map);
//readMethodByEntry(map);

System.out.println(map);
}
}


 

    4、HashMap类*

        

     

/*
需求:每一个学生都有对应的归属地。
学生Student,地址String。
学生属性:姓名,年龄。
注意:姓名和年龄相同的视为同一个学生,保证学生的唯一性。

分析:
1、描述学生。
2、定义map容器。将学生作为键,地址作为值。存入。
3、获取map集合中的元素。
*/

import  java.util.*;

class Student implements Comparable<Student>{//使类具有自然的比较顺序,为了存入TreeSet;以及广泛使用。
private String name;
private int age;

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

public int compareTo(Student stu){//指定了类型

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

if(num ==0)
return  this.name.compareTo(stu.name);

return num;
}

public int hashCode(){
return name.hashCode()+age*37;//37是处理name和age不同,但是相加值相同的情况
}

public boolean equals(Object obj){
if(!(obj instanceof Student))
//return false;
throw  new ClassCastException("Type mismatch!");

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

public void setName(String name){
this.name = name;
}

public String getName(){
return name;
}

public void setAge(int age){
this.age = age;
}

public int getAge(){
return age;
}

public  String toString(){
return  (this.name+":"+this.age);
}
}

class  MapTest{
public static void readMethodByKey(Map map){
Set<Student>  set = map.keySet();
for(Iterator<Student>  it = set.iterator();it.hasNext();){
Student key  = it.next();

String values =  (String)map.get(key);
System.out.println("key= "+key+"->"+"values= "+values);
}
}

public static void readMethodByEntry(Map map){
Set<Map.Entry<Student,String>>  entry  = map.entrySet();

for(Iterator<Map.Entry<Student,String>>  it = entry.iterator();it.hasNext();){
Map.Entry<Student,String> mapEntry = it.next();

Student key  = mapEntry.getKey();
String values = mapEntry.getValue();

System.out.println("key= "+key+"->"+"values= "+values);
}

}

public static void main(String[] args) {
Map<Student,String>   map = new  HashMap<Student,String>();

map.put(new Student("java01",20),"abc0");
map.put(new Student("java02",22),"abc1");
map.put(new Student("java03",25),"abc2");
map.put(new Student("java04",30),"abc3");
map.put(new Student("java05",21),"abc4");

readMethodByKey(map);
//readMethodByEntry(map);

System.out.println(map);
}
}


 

    5、TreeMap类

      (1)public TreeMap(Comparator<? super K> comparator);

        

import java.util.*;

class nameComparator implements Comparator<Student>{
public  int  compare(Student s1,Student s2){
int  value  =  s1.getName().compareTo(s2.getName());
if(value ==0){
return  new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
}
return value;
}
}

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

map.put(new Student("java01",20),"abc0");
map.put(new Student("java02",22),"abc1");
map.put(new Student("java03",25),"abc2");
map.put(new Student("java04",30),"abc3");
map.put(new Student("java04",30),"abc5");
map.put(new Student("java05",21),"abc4");

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

for(Iterator<Map.Entry<Student,String>> it = entryset.iterator();it.hasNext();){
Map.Entry<Student,String>  me  =  it.next();

Student stu = me.getKey();
String  addr = me.getValue();

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


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

      

/*
练习:
"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。

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

思路1:
1、字母->次数 :Map映射关系;
字母为键值,次数为值

2、处理字符串,存入到Map中,计算次数;
a、把字符串处理成char[];
b、for-for循环处理;
c、记录每个字母次数;
d、把字母和次数存入Map集合。

3、打印Map映射。

思路2:
1、将字符串转换成字符数组。因为要对每一个字母进行操作。

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

3、遍历字符数组。
将每一个字母作为键去查map集合。
如果返回null,将该字母和1存入到map集合中。
如果返回不是null,说明该字母在map集合已经存在并有对应次数。
那么就获取该次数并进行自增。,然后将该字母和自增后的次数存入到map集合中。覆盖调用原理键所对应的值。

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

import java.util.*;

class MapTest3 {
public static String charCount(String str){
Map<Character,Integer> map = new TreeMap<Character,Integer>();
/*
char[] arr = str.toCharArray();
for(int i =0;i<arr.length;i++){
int count =0;
char s = arr[i];
for(int j=0;j<arr.length;j++){
if(arr[i]==arr[j])
count++;
}

map.put(new Character(arr[i]),new Integer(count));
}
*/

//char[] arr = str.toCharArray();
//for(int i =0;i<arr.length;i++){
//Integer value = map.get(arr[i]);
//if(value == null){
//map.put(arr[i],1);
//}
//else{
//map.put(arr[i],(value+1));
//}
//}

char[] arr = str.toCharArray();
int count =0;
for(int i =0;i<arr.length;i++){

if((arr[i]>='a'&&arr[i]<='z')||(arr[i]>='A'&&arr[i]<='Z')){
count =0;
Integer value = map.get(arr[i]);
if(value != null)
count = value;
count++;
map.put(arr[i],count);
}

}

StringBuilder  sb = new StringBuilder();
Set<Map.Entry<Character,Integer>> entryset = map.entrySet();
for(Iterator<Map.Entry<Character,Integer>> it = entryset.iterator();it.hasNext();){
Map.Entry<Character,Integer>  me  =  it.next();

Character charc = me.getKey();
Integer   num = me.getValue();

sb.append(charc+"("+num+")");
}

return sb.toString();
}

public static void main(String[] args){
String  str = "sdf-gzxcvasdfx-cvdf";

String  s  = charCount(str);
System.out.println(s);
}
}


 

    6、Map扩展:把集合作为元素存储到Map中

       

   

/*
需求:用Map描述一个公司的结构。

销售部:工号  姓名

开发部:工号  姓名
*/

import  java.util.*;

class Employee{

private  String workNumber;
private  String name;

Employee(String workNumber,String name){
this.workNumber = workNumber;
this.name = name;
}

public String toString(){
return   (workNumber+"::"+name);
}

}

class MapDemo3{

public static  void  methodOne(){
HashMap<String,List<Employee>>  company =  new HashMap<String,List<Employee>>();

List<Employee>  develop  =  new ArrayList<Employee>();
List<Employee>  sale  =  new ArrayList<Employee>();

company.put("sale",sale);
company.put("develop",develop);

sale.add(new Employee("101","abc0"));
sale.add(new Employee("102","abc1"));

develop.add(new Employee("103","abc2"));
develop.add(new Employee("104","abc3"));

Iterator<String> it = company.keySet().iterator();
while(it.hasNext()){
String  department = it.next();
List<Employee> departmentName = company.get(department);

System.out.println(department);
Iterator<Employee> its = departmentName.iterator();
while(its.hasNext()){
Employee  employee = its.next();
System.out.println(employee);
}
}
}

public static  void  methodTwo(){
HashMap<String,HashMap<String,String>>  company =  new HashMap<String,HashMap<String,String>> ();

HashMap<String,String>  develop  =  new HashMap<String,String>();
HashMap<String,String>  sale  =  new HashMap<String,String>();

company.put("sale",sale);
company.put("develop",develop);

sale.put("101","abc0");
sale.put("102","abc1");

develop.put("103","abc2");
develop.put("104","abc3");

Iterator<String> it = company.keySet().iterator();
while(it.hasNext()){
String  department = it.next();
HashMap<String,String> departmentName = company.get(department);

System.out.println(department);
Iterator<String> its = departmentName.keySet().iterator();
while(its.hasNext()){
String  workNumber = its.next();
String  name = departmentName.get(workNumber);
System.out.println(workNumber+"::"+name);
}
}
}

public static void main(String[] args)
{

methodOne();
//methodTwo();
}
}


 

八、比较

    1、比较器:Comparator接口

       (1)对象数组:对应自定义类的比较器需要继承Comparator接口,和覆盖 int compare(T o1,T o2)方法;

       (2)对象集合:对应自定义类的比较器需要继承Comparator接口,和覆盖 int compare(T o1,T o2)方法;

                      并通过集合的构造函数把比较器传入。

    2、自然比较方式:Comparable接口 

       自定义类需要需要继承Comparable接口,和覆盖 int compareTo(T o)方法;

      

   

/*
需求:按照字符串长度排序。
*/

import java.util.*;

class TreeSetTest {
public static void main(String[] args){
TreeSet ts = new TreeSet(new MyComparator());

ts.add("abcde");
ts.add("cd");
ts.add("bc");
ts.add("dte");
ts.add("iop");

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

class  MyComparator 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;
}
}


 

   

九、包装器

    1、Collections

      (1)Collections:集合框架的工具类。里面定义的都是静态方法。

      (2)Collections和Collection区别:

           Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。它有两个常用的子接口,

  List:对元素都有定义索引。有序的。可以重复元素。

  Set:不可以重复元素。无序。

           Collections是集合框架中的一个工具类。该类中的方法都是静态的。

   提供的方法中有可以对list集合进行排序,二分查找等方法。

   通常常用的集合都是线程不安全的。因为要提高效率。

   如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。

      (3)常用算法

            a、排序

  public static <T> void sort(List<T> list,Comparator<? super T> c);

  public static <T extends Comparable<? super T>> void sort(List<T> list);//针对List接口中的对象对应的类。

           

     b、最大值

        public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll);

        public static <T> T max(Collection<? extends T> coll,Comparator<? super T> comp);

            c、查找

        public static <T> int binarySearch(List<? extends Comparable<? super T>> list,T key);

        public static <T> int binarySearch(List<? extends T> list, T key,Comparator<? super T> c);

            

import java.util.*;

class StrLenComparator implements Comparator<String>{
public int compare(String s1,String s2){

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

return num;
}
}

class  CollectionsDemo{
public static void main(String[] args) {
//sortDemo();

//maxDemo();

binarySearchDemo();
}

public static void binarySearchDemo(){
List<String> list = new ArrayList<String>();

list.add("abcd");
list.add("aaa");
list.add("zz");
list.add("kkkkk");
list.add("qq");
list.add("z");

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

sop(list);

//int index = Collections.binarySearch(list,"aaaa");
//int index = halfSearch(list,"cc");
int index = halfSearch2(list,"aaa",new StrLenComparator());
sop("index="+index);
}

//binarySearch()方法内部的实现
public static int halfSearch(List<String> list,String key){
int max,min,mid;
max = list.size()-1;
min = 0;

while(min<=max)
{
mid = (max+min)>>1;//  /2;

String str = list.get(mid);

int num = str.compareTo(key);
if(num>0)
max = mid -1;
else if(num<0)
min = mid + 1;
else
return mid;
}
return -min-1;//
}

public static int halfSearch2(List<String> list,String key,Comparator<String> cmp){
int max,min,mid;
max = list.size()-1;
min = 0;

while(min<=max)
{
mid = (max+min)>>1;//  /2;

String str = list.get(mid);

int num = cmp.compare(str,key);//自定义的比较器的比较方法
if(num>0)
max = mid -1;
else if(num<0)
min = mid + 1;
else
return mid;
}
return -min-1;
}
//binarySearch()方法内部的实现

public static void maxDemo(){
List<String> list = new ArrayList<String>();

list.add("abcd");
list.add("aaa");
list.add("zz");
list.add("kkkkk");
list.add("qq");
list.add("z");
list.add("bbbbb");
Collections.sort(list);
sop(list);
//String max = Collections.max(list);
String max = Collections.max(list,new StrLenComparator());
sop("max="+max);
}

public static void sortDemo(){
List<String> list = new ArrayList<String>();

list.add("abcd");
list.add("aaa");
list.add("zz");
list.add("kkkkk");
list.add("qq");
list.add("z");

sop(list);

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

}

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


     

     d、替换

        public static <T> void fill(List<? super T> list,T obj);

        public static <T> boolean replaceAll(List<T> list,T oldVal,T newVal);

        public static void swap(List<?> list,int i,int j);

     e、反转和反转规则

        public static void reverse(List<?> list);

        public static <T> Comparator<T> reverseOrder();

        public static <T> Comparator<T> reverseOrder(Comparator<T> cmp);

       

import java.util.*;

//反向
class StrComparator implements Comparator<String>
{
public int compare(String s1,String s2)
{
/*
int num = s1.compareTo(s2);
if(num>0)
return -1;
if( num<0)
return 1;
return num;
*/

return s2.compareTo(s1);
}
}

class StrLenComparator implements Comparator<String>{
public int compare(String s1,String s2){

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

return num;
}
}

class  CollectionsDemo2{
public static void main(String[] args) {
//replaceDemo();
//reverseDemo();
//reverseorderDemo();
shuffleDemo();
}

public static void shuffleDemo(){
List<String> list = new ArrayList<String>();

list.add("abcd");
list.add("aaa");
list.add("zz");
list.add("kkkkk");
list.add("qq");
list.add("z");
sop(list);

Collections.shuffle(list);
sop(list);
}

public static void reverseorderDemo(){
//TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder());
TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new StrLenComparator()));

ts.add("abcde");
ts.add("aaa");
ts.add("k");
ts.add("cc");

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

public static void  reverseDemo(){
List<String> list = new ArrayList<String>();

list.add("abcd");
list.add("aaa");
list.add("zz");
list.add("kkkkk");
list.add("qq");
list.add("z");
sop(list);

Collections.reverse(list);
sop(list);
}

public static void replaceDemo(){
List<String> list = new ArrayList<String>();

list.add("abcd");
list.add("aaa");
list.add("zz");
list.add("kkkkk");
list.add("qq");
list.add("z");
sop(list);

//Collections.fill(list,"pp");
//sop(list);

//fillPrcessList(list,2,4);
//sop(list);

Collections.swap(list,1,4);
sop(list);
}

public static void fillPrcessList(List<String> list,int start,int end){
List<String> temp  =  list.subList(start,end+1);

Collections.fill(temp,"pp");

for(int i=start,j=0;i<=end;i++,j++){
Collections.replaceAll(list,list.get(i),temp.get(j));
}
}

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


 

     f、多线程同步

        public static <T> Collection<T> synchronizedCollection(Collection<T> c);

        public static <T> List<T> synchronizedList(List<T> list);

        public static <T> Set<T> synchronizedSet(Set<T> s);

        public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m);

              

     

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

      (1)指定类型的数组要定义长度:

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

        当指定类型的数组长度大于了集合的size,就不会新创建了数组。而是使用传递进来的数组,就会有null值存入多出来的部分。

           所以利用size()方法创建一个刚刚好的数组最优。

 (2)将集合变数组目的:

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

      

import java.util.*;
class  CollectionsToArray{
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();

al.add("abc1");
al.add("abc2");
al.add("abc3");

//String[] arr = al.toArray(new String[0]);//[abc1, abc2, abc3]

//String[] arr = al.toArray(new String[5]);//[abc1, abc2, abc3, null, null]
String[] arr = al.toArray(new String[al.size()]);

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


 

    3、Arrays类

       (1)Arrays:用于操作数组的工具类。里面都是静态方法。

  public static <T> void sort(T[] a, Comparator<? super T> c);

  public static void sort(Object[] a);//针对数组,任何元素组成的,包括自定义类组成的。

  public static <T> int binarySearch(T[] a,T key,Comparator<? super T> c);

       (2)将数组变成list集合:asList()

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

     b、将数组变成集合,不可以使用集合的增删方法。因为数组的长度是固定。只能使用:

   contains();

   get();

   indexOf();

   subList();

        如果你增删。那么会反生UnsupportedOperationException,

     c、如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。

         如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。

 

import java.util.*;

class  ArraysDemo{
public static void main(String[] args) {
//int[] arr = {2,4,5};
//System.out.println(Arrays.toString(arr));

//String[] arr = {"abc","cc","kkkk"};
//List<String> list = Arrays.asList(arr);
//sop("contains:"+list.contains("cc"));
////list.add("qq");//UnsupportedOperationException,
//sop(list);

int[] nums = {2,4,5};
List li = Arrays.asList(nums);//[[I@1db9742] 等价于  List<int[]> li = Arrays.asList(nums);
sop(li);

Integer[] num = {2,4,5};
List<Integer> lis = Arrays.asList(num);
sop(lis);
}

public static boolean myContains(String[] arr,String key){
for(int x=0;x<arr.length; x++){
if(arr[x].equals(key))
return true;
}
return false;
}

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

}


 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  集合 java