Collection与Map

Posted 海洋初光

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Collection与Map相关的知识,希望对你有一定的参考价值。

一、collection框架

 (1)LIST

list是一种collection,作用是收集对象,并以索引的方式保留收集的对象的顺序。其操作类之一就是Java.utl.ArrayList.ArrayList特性:随机查找(list.get[i]),ArrayList内部就是用Object来保存收集的对象。此时就考虑到了数组的特性。根据数据结构内容我们只数组的好处就是随机存储速度快,排序等就可以考虑使用ArrayList

package Learn;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;

public class ListDemo {
    public static void main(String[] args) {
        List name=new ArrayList();//收集信息的list
        collectNameTo(name);//收集函数
        System.out.println("输出访客名单:");
        printUpperCase(name);//输出收集到的信息
    }
    /**
     *@author wbm
     *@param List
     *@deprecated通过控制台输入访客的名称,如果遇到quit则退出输入访客名称的循环,每次循环都把收集到的信息通过List.add(信息对象)收集到list中去
     */
        
    
     static void collectNameTo(List names){
        Scanner console=new Scanner(System.in);//控制台输入信息
        while(true){
            System.out.println("访客名称:");
            String name=console.nextLine();
            if(name.equals("quit")){
                break;
            }
            names.add(name);//把控制台输入的信息放入到list中去
        }
    }
     /**
      *通过for循环把传进来的List通过索引获取list元素并转换为string性,然后通过string的toUpperCase()转为大写
      */
     static void printUpperCase(List names){
         for (int i = 0; i < names.size(); i++) {
            String name=(String) names.get(i);//通过索引获得收集的信息
            System.out.println(name.toUpperCase());

         }
     }

}
View Code

LinkedList特性:采用链接结构。链接结构简单代码如下。

package Learn;

public class LinkListDemo {
    private class Node{
        Object o;
        Node next;
        Node(Object o){
            this.o=o;
        }
    }
    private Node first;
    public void add(Object elem){
        Node node=new Node(elem);
        if(first==null){
            first=node;
        }
        else{
            append(node);
        }
    }
    private void append(Node node){
        Node last=first;
        while(first.next!=null){
            last=last.next;
        }
        last.next=node;
    }
    public int size(){
        int count=0;
        Node last=first;
        while(last.next!=null){
            last=last.next;
            count++;
        }
        return count;
    }
    public Object get(int index){
        checkSize(index);
        return findElemof(index);
    }
    private void checkSize(int index)throws IndexOutOfBoundsException{
        int size=size();
        if(index>=size){
            throw new IndexOutOfBoundsException( String.format("index:%d size:%d", index,size));
            
        }
    }
    private Object findElemof(int index){
        int count=0;
        Node last=first;
        while(count<index){
            last=last.next;
            count++;
        }
        return last.next;
    }

}
View Code

  (2)set

 也是收集对象,但是对象相同则不重复收集。知道不重复单词个数有几个代码如下。

public static void mian(String[] args) {
        // TODO Auto-generated method stub
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入英文");
        Set words=tokenSet(scanner.nextLine());//scanner.nextLine()String类型
        System.out.printf("不重复的字有%d个:%s%n",words.size(),words);
    }
    static Set tokenSet(String line){
        String[] tokens=line.split(" ");//根据空白切割字符串
        return new HashSet(Arrays.asList(tokens));//使用HashSet收集字符串
        
    }
View Code

使用set时得告诉怎样的对象是相同,这时要用对象的hashCode()和equals()来判断对象是够相同。HashSet的操作哦该娘是,在内存中开设空间,每个空间都会有哈希编码,这些空间称为哈希桶,如果对象要加入哈希桶,则要调用对象的hashcode(),并尝试放入对应的哈希桶中,如果哈希桶中没有对象就放入,如果有对象就调用equals()进行比较。有无equals和hashcode的对比代码如下

package Learn;

import java.util.HashSet;
import java.util.Set;

 class Student {
    private String name;
    private String number;
    Student(String name,String number){
        this.name=name;
        this.number=number;
    }
    @Override
    public String toString() {
        return "Student [name=" + name + ", number=" + number + "]";
    }

    
}

package Learn;

import java.util.HashSet;
import java.util.Set;

public class Students {
    
        public static void main(String[] args) {
            Set students=new HashSet();
            students.add(new Student("b","c"));
            students.add(new Student("b","c"));
            students.add(new Student("q","c"));
        System.out.println(students);

    }

}
结果:
[Student [name=q, number=c], Student [name=b, number=c], Student [name=b, number=c]]
package Learn;

import java.util.HashSet;
import java.util.Set;

 class Student {
    private String name;
    private String number;
    Student(String name,String number){
        this.name=name;
        this.number=number;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + ((number == null) ? 0 : number.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (number == null) {
            if (other.number != null)
                return false;
        } else if (!number.equals(other.number))
            return false;
        return true;
    }
    @Override
    public String toString() {
        return "Student [name=" + name + ", number=" + number + "]";
    }
    
}
结果:
[Student [name=b, number=c], Student [name=q, number=c]]
View Code

java.util.TreeSet不仅有收集不重复对象的能力,还可以用红黑树的方式排序收集到的对象,条件就是收集到的对象必须是Comparable(否则会抛出ClassCastException),或者是在创建的是后指定comparator对象

 (3)quene

支持队列操作,收集的对象加入至尾部,取得的对象时从前部,quene继承自collection所以有add、remove、element等方法然而quene定义了自己的offer、poll、peak等方法主要区别在于,add、remove、element等方法操作失败时会抛出异常,而offer、poll、peak会返回特定的值。对象需要使用队列且长度受限是用通常使用poll、offer、peak方法。从架构图可知linkedList不仅操作了queue的行为也操作了list的行为。所以可以将linkedlist当做队列来使用。

简单的代码实例如下:

package Learn;

public interface Request {
     void execute();

}

package Learn;

import java.util.*;
/**
 * offer是在队列前端加入对象成功会返回trues失败会返回false。
 * poll是去除队列的前端对象,若队列为空则返回null。
 * peak是取得前端对象但是不取出若为空则返回null。
 * */
public class RequestQuene{
    public static void main(String[] args) {
        Queue requests=new LinkedList();
        offerRequestTo(requests);
        process(requests);
    }
    static void offerRequestTo(Queue requests){
        //请求加入队列
        for(int i=1;i<6;i++){
            Request request=new Request(){
                @Override
                public void execute() {
                    // TODO Auto-generated method stub
                    System.out.printf("处理数据%f%n",Math.random());
                }
            };
            requests.offer(request);
            System.out.println(requests.offer(request));
        }
    }
    static void process(Queue requests){
        //处理队列中的请求
        while(requests.peek()!=null){
            Request request=(Request)requests.poll();
            request.execute();
        }
    }
    
}
View Code

如果想要对队列的前端和尾端进行操作,在前端加入对象和取出对象,在尾端加入对象和取出对象,queue的子接口Deque就定义了该行为。deque中定义addFirst()、removeFirst()、getFirst()、addLast()、

removeLast()、getLast()等方法,操作失败时会抛出异常。而offerFirst()、pollFirst()、peekFirst()、offerLast()、pollLast()、peekLast()操作失败会返回特定的值。java.util.ArrayDeque操作了Deque接口,操作使用容量有限的堆栈的简单实例如下

package Learn;

import java.util.*;

public class Stack {
    private Deque elems=new ArrayDeque();
    private int capacity;
    Stack(int capacity){
        this.capacity=capacity;
    }
    public boolean push(Object elem){
        if(isFull()){
            return false;
        }
        else{
            return elems.offerLast(elem);
        }
    }
    private boolean isFull(){
        return elems.size()+1>capacity;
    }
    public Object pop(){
        return elems.pollLast();
    }
    public Object peek(){
        return elems.peekLast();
    }
    public int size(){
        return elems.size();
    }
    public static void main(String[] args) {
        Stack stack=new Stack(5);
        stack.push("justin");
        stack.push("wbm");
        stack.push("wcy");
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
    }

}
结果:
wcy
wbm
justin
堆栈是先进后出
View Code

queue的操作类之一java.util.PriorityQueue也是,收集至PriorityQueue的对象,会根据你指定的优先权来决定对象在队列中的顺序,优先的告知,要不是对象必须是comparable,或者是在创建PriorityQueue时指定comparator对象。

(3)Interable与Iterator

iterator方法JDK5之前是定义在collection中在JDK5之后定义在iterable;具体的一些好处和细节如下代码。

    //收集LIst对象
    static void forEachList(List list){
        int size=list.size();
        for(int i=0;i<size;i++){
            System.out.println(list.get(i));
        }
    }
    //收集set对象
    static void forEachSet(Set set){
        for(Object o:set.toArray()){
            System.out.println(o);
        }
    }
    //收集queue对象
    static void forEachQueue(Queue queue){
        while(queue.peek()!=null){
            System.out.println(queue.poll());
        }
    }
    //含有这个方法的类是util,那么你就可以指定使用util.<String> elemOf()的方式指定E的实际类型
    public static<E> E elemOf(E[] objs,int index){
        return objs[index];
    }
    //无论是Queue、List、Set都会有iterator方法JDK5之前是定义在collection中在JDK5之后定义在iterable
    static void forEachCollection(Collection collection){
        Iterator iterator=collection.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
    static void forEachIterable(Iterable iterable){
        Iterator iterator=iterable.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
View Code
package Learn;

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;

public class forEach {
    public static void main(String[] args) {
        List names=Arrays.asList("ww","bb","mm");//静态方法aslist接收不定长自变量将其指定为List
        forEach(names);//list是一种Iterable.
        forEach(new HashSet(names));//List是一种collection,hashSet是一种collection接收collection的构造函数所以list可以用来创建hashset
        forEach(new ArrayDeque(names));//同理
    }
    static void forEach(Iterable iterable){
        for (Object object : iterable) {
            System.out.println(object);
        }
        
    }

}
View Code

(4)comparable与comparator

 1. comparable(comparaTo())   

  在收集对象之后,对对象排序是常用的动作,我们不用亲自操作排序算法,java.util.collections

List numbers=Arrays.asList(10,5,1,9,8,9,7);
        Collections.sort(numbers);
        System.out.println(numbers);
结果为:[1, 5, 7, 8, 9, 9, 10]
View Code

  如果没有说明list元素的比较会出现错误

package Learn;

import java.util.HashSet;
import java.util.Set;

 class Student {
    private String name;
    private String number;
    Student(String name,String number){
        this.name=name;
        this.number=number;
    }
    @Override
    public String toString() {
        return "Student [name=" + name + ", number=" + number + "]";
    }
}

package Learn;

import java.util.Arrays;
import java.util.Collections;

import java.util.List;


public class Students {
        public static void main(String[] args) {
            List students=Arrays.asList(new Student("b","c"),new Student("b","c"),new Student("q","c"));
            Collections.sort(students);
        System.out.println(students);

    }
}
出现:
java.lang.ClassCastException:
View Code

collections.sort()的操作对象必须操作java.lang.comparable接口,这个接口有compareTo()方法的返回值必须大于0,等于0或小于0的整数。

package Learn;

import java.util.HashSet;
import java.util.Set;

 public class Student implements Comparable<Student> {
    private String name;
    private String number;
    Student(String name,String number){
        this.name=name;
        this.number=number;
    }
    @Override
    public String toString() {
        return "Student [name=" + name + ", number=" + number + "]";
    }
    @Override
    public int compareTo(Student o) {
        // TODO Auto-generated method stub
        return Integer.parseInt(this.number)-Integer.parseInt(o.number);
    }
}

package Learn;

import java.util.Arrays;
import java.util.Collections;

import java.util.List;


public class Students {
        public static void main(String[] args) {
            List students=Arrays.asList(new Student("b","1"),new Student("b","3"),new Student("q","2"));
            Collections.sort(students);
        System.out.println(students);

    }
}

结果为
[Student [name=b, number=1], Student [name=q, number=2], Student [name=b, number=3]]
View Code

2.compatator(compare())

如果对象无法操作comparable的话呢?比如String本身有操作Comparable,所以可以按字母的排序如果我想要把字母排序的顺序反过来呢?String是final的类型不能被继承所以无法重新定义compareTo()方法。Collection有另一个重载版本,可以接受java.lang.Comparator接口的操作对象。流程:1.定义一个comparator:class StringComparator implements<String>{ public int compare(String s1,String s2){ return s1.compareTo(s2);}}  2.调用:Collections.sort(List,new StringComparator());

package Learn;

import java.util.Comparator;

public class StringComparator implements Comparator <String> {

    @Override
    public int compare(String o1, String o2) {
        // TODO Auto-generated method stub
        return -o1.compareTo(o2);
    }

}


package Learn;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class sort {
    public static void main(String[] args) {
        List<String> words=Arrays.asList("B","A","C");
        Collections.sort(words,new StringComparator());
        System.out.println(words);
    }
}
结果
[C, B, A]
View Code

 

二、Map框架

1.hashMap

  1)概述

    基于哈希表的Map接口的非同步实现。实现所有的可选映射操作,允许使用null键和null值。此类不保证映射的顺序。

   2)数据结构

  3)简单使用HashMap

对于Map而言键值是不会重复,判断键是否重复式根据hashcode和equals(),所以作为键的对象必须操作hashcode()与equals()

public static void main(String[] args) {
        Map<String,String> messages=new HashMap<String,String>();
        messages.put("1", "one");
        messages.put("2", "two");
        messages.put("3", "three");
        Scanner scanner=new Scanner(System.in);
        String message=messages.get(scanner.nextLine());
        System.out.println(message);
        System.out.println(messages);
    }
结果为:
1
one
{1=one, 2=two, 3=three}
View Code

2.TreeMap

  键的部分会排序,条件式作为键的对象必须操作Comparable接口,或者是在创建TreeMap时指定Comparator接口的对象。

    public static void main(String[] args) {
        Map<String,String> messages=new TreeMap<String,String>();
        messages.put("1", "one");
        messages.put("2", "two");
        messages.put("3", "three");
        System.out.println(messages);
    }
}
结果为:
{1=one, 2=two, 3=three}
View Code

3.使用Properties

Properties props=new Properties();
        props.setProperty("username", "justin");
        props.setProperty("password", "123456");
        System.out.println(props.getProperty("username"));
        System.out.println(props.getProperty("password"));
//从文档中读取属性
//文档内容a.properties 
/*
cc.openhome.username=justin
cc.openhome.password=123456
*/
Properties props=new Properties();
        props.load(new FileInputStream("args[0]"));
        System.out.println(props.getProperty("cc.openhome.username"));
        System.out.println(props.getProperty("cc.openhome.password"));
View Code

三、简单泛型的使用

  在使用Collection收集对象时,由于事先不知道对象的形态使用的是Object来收集,取回对象也是Object,所以执行期间失去了形态的信息。所以取回对象之后要记得对象的真正的类型,然后让对象重新扮演

  自己的类型。

List names=Array.asList("ww","bb","mm");
String name=(String)name.get(0);
ArrayList<String> names= new ArrayList<String>();
names.add("justin");
names.add("wbm");
names.add(new Long(10));//编译会出错没法通过。
String name1=names.get(0);
string nmae2=names.get(1);
View Code

 静态方法上定义类型

//含有这个方法的类是util,那么你就可以指定使用util.<String> elemOf()的方式指定E的实际类型
    public static<E> E elemOf(E[] objs,int index){
        return objs[index];
    }

 补充:

Utilizes

  Collections:是针对集合类的一个帮助类,提供了操作集合的工具方法:一系列静态方法实现对各种集合的搜索、排序、线程

        安全化等操作。

  Arrays:针对数组的一个帮助类,提供了操作arrays的工具方法:一系列静态方法对各种数组的搜索、排序等操作

 

    

 

以上是关于Collection与Map的主要内容,如果未能解决你的问题,请参考以下文章

Collection与Map

Collection与Map的对比

集合类 collection接口 ArrayList

Java map Collection到Collection

HashMap

java基础- Collection和map