JavaJava学习笔记

Java学习笔记 (三)

2016-06-09  本文已影响45人  翌日千里

Object类:完整的类最好覆写Object类的hashCode()equals()toString()3个方法。
在类集中提供了4种常见的输出方式:

  1. Iterator:迭代输出,使用最多的输出方式。
  2. ListIterator:Iterator的子接口,专门用于输出List中的内容。
  3. Enumeration:是旧接口,功能与Iterator类似。
  4. foreach:jdk1.5之后新增,输出数组和集合。
Iterator——迭代器:
  1. 二要素:
    i. 迭代器必定从属于某个容器,其作用就是用来遍历所属容器中的元素的。
    ii.迭代器是在容器的数据视图之上进行迭代,因此不能再迭代过程中修改容器中的数据,否则会抛出异常!除非使用迭代器的专用方法对数据进行修改。
  2. Java的迭代器只在Collection中有,而Map没有迭代器,它有不同的迭代方法。
  3. 迭代器的终极目标:就是用统一的方法来迭代不同类型的集合!可能由于不同集合的内部数据结构不尽相同,如果要自己纯手工迭代的话相互之间会有很大的差别,而迭代器的作用就是统一的方法对不同的集合进行迭代,而在迭代器底层隐藏不同集合之间的差异,从而为迭代提供最大的方便。
  4. 用迭代器迭代的步骤:
    i. 第一步肯定是先获取集合的迭代器:调用集合的iterator方法就能获得,Iterator<E> Collection.iterator(); // 是Collection的对象方法
    ii. 使用迭代器的hasNext、next往下迭代。
Iterator的常用方法:
* boolean hasNext(); // 是否还有下一个元素(肯定有一个位置指针维护者当前迭代的位置)
* Object next();        // 取出下一个元素并返回
* void remove();       // 从容器中删除当前元素(即上一个next代表的那个元素),直接会改变容器中的数据!  

 由于Java容器都是泛型类模板,因此容器可以记忆元素的具体类型,因此可以放心使用,只不过取出元素后要进行类型转换后才能正常使用,
使用迭代器next获得的元素是一个集合中对应元素的深拷贝(即数据视图),如果对迭代变量进行修改是不会修改集合中的原数据的。同样,也不能直接在迭代过程中使用c.remove等方法对集合进行修改,因为迭代器已经锁定住集合了,强行修改会抛出异常!只能用Iterator的专用修改集合元素的方法修改才是正确的,就像上面的Iterator.remove方法。
模板:

public class Test {  
      
    public static void main(String[] args) {  
        Collection c = new ArrayList(); // ArrayList是Collection的一个实现类,默认元素类型为Object  
          
        Iterator it = c.iterator();  
        while (it.hasNext()) {  
            Type var = it.next(); // 迭代值(数据视图)  
            对var进行操作;  
            c.remove(); // 错误!!在迭代过程中使用非迭代器方法对集合进行修改会直接抛出异常!!  
        }  
    }  
}  

实际上,Iterator迭代的“集合”是真正集合的视图,视图和真实数据之间是一一映射的关系,如果此时使用非迭代器方法对真实数据进行修改就会导致真实数据和映像之间不一致,因此会抛出异常,而迭代器的修改方法可以保证这种映射的一致性,即迭代器先对视图进行修改,然后将视图的修改更新到真实数据,但是反向就是无效的,因为映像自己是知道关联的是哪个真实数据,但是真实数据本身不知道有哪些映像和我关联的,即真实数据永远是被动的,而映像是主动的。

ListIterator

ListIterator是Iterator的子接口,专门用于输出List中的内容。只能从List接口实例化。可以进行双向迭代。

public class ListIteratorDemo01{
    public static void main(String argsp[]){
        List<String> all = new ArrayList<String>() ;
        all.add("hello") ;
        all.add("_") ;
        all.add("world") ;
        ListIterator<String> iter = all.listIterator() ;
        System.out.print("由前向后输出:") ;
        while(iter.hasNext()){
            String str = iter.next() ;
            System.out.print(str + "、") ;
        }
        System.out.print("\n由后向前输出:") ;
        while(iter.hasPrevious()){
            String str = iter.previous() ;
            System.out.print(str + "、") ;
        }
    }
};

输出结果:
由前向后输出:hello、、world、
由后向前输出:world、
、hello、

Map接口
Map 图谱

Map 就是关联数组,也常被称为“映射表”或是“字典”,是键值对的集合容器,键不能重复出现是他的基本限制

如上图所示,Map 都继承自 Map 接口,标准 Java 类库中包含了几种 Map 的基本实现:

  1. TreeMap -- 基于红黑树的 Map 实现,因此是有序的,作为键加入 TreeMap 的对象必须实现 Comparable 接口,以便他可以被比较
  2. HashMp -- 基于哈希表的 Map 实现,虽然无序,但是优势却在于其查询速度
  3. LinkedHaskMap -- 在 HashMap 的基础上实现的双链表复合结构,在查询速度的基础上保证了插入顺序
  4. WeakHashMap -- WeakHashMap 与 HashMap 的用法基本相同,Hash 的 key 保留对象的强引用,即只要 HashMap 5. 对象不被销毁,其对象所有 key 所引用的对象不会被垃圾回收,HashMap 也不会自动删除这些key所对应的键值对对象。但 WeakHashMap 的 key 所引用的对象没有被其他强引用变量所引用,则这些 key 所引用的对象可能被回收。WeakHashMap 中的每个 key 对象保存了实际对象的弱引用,当回收了该 key 所对应的实际对象后,WeakHashMap 会自动删除该key所对应的键值对
  5. ConcurrentHashMap -- ConcurrentHashMap 保证了线程安全,一般用在多线程环境中
  6. IdentityHashMap -- 与 HashMap 一样,IdentityHashMap 也不保证存储的顺序,他与 HashMap 的区别在于,它用来比较键是否相同的方法是 == 而不是 equals 方法,因此值相同但地址不同的两个对象是允许出现的,一般只在解决特殊问题时才会使用

Map 接口定义了基本的 map 操作方法:

方法名 方法 说明
get V get(Object key) 获取 key 对应的值
put V put(K key, V value) 向容器中添加键值对
putAll void putAll(Map m) 将 Map m 中的所有元素添加到容器中
remove V remove(Object key) 删除指定的 key
clear void clear() 清除容器中所有元素
containsKey boolean containsKey(Object key) 判断 key 是否存在
containsValue boolean containsValue(Object value) 判断 value 是否存在
isEmpty boolean isEmpty() 判断容器是否为空
keySet Set keySet() 返回由所有 key 组成的 set
values Collection values() 返回由所有 value 组成的 Collection
entrySet Set> entrySet(); 获取 Map 内部接口 Entry 组成的 Set

TreeMap : String类型实现了comparable接口,如果使用自定义类的话需要先实现Comparable接口。
对象的四种引用方式:

总结:强引用的对象一定不会被当成垃圾回收的,软引用的对象会在内存不足时被当成垃圾回收掉,弱引用的对象在下一次垃圾回收时就直接回收掉。

Map接口的注意事项:

  1. 不能直接使用迭代(Iterator,foreach)输出Map中的全部内容。如果要用需按照以下4步。
    a. 将map的实例通过entrySet()方法变为Set接口对象。
    b. 通过Set接口实例为Iterator实例化。
    c. 通过Iterator迭代输出,每个内容都是Map.Entry的对象。
    d. 通过Map.Entry进行key→value的分离。
public class IteratorDemo04 {
    public static void main(String[] args) {
        Map<String, String> map = null;     // 声明Map对象,其中key和value的类型为String
        map = new HashMap<String,String>();
        map.put("lc", "lichuang");      // 增加内容
        map.put("jsf", "jisaifu");      // 增加内容
        map.put("wzc", "wangzhicheng");     // 增加内容
        Set<Map.Entry<String, String>> allSet = null;
        allSet = map.entrySet();
        Iterator<Map.Entry<String, String>> iter = null;
        iter = allSet.iterator();
        while (iter.hasNext()) {
            Map.Entry<String, String> me = iter.next();
            System.out.println(me.getKey() + "-->" + me.getValue());
        }
    }
}
执行结果:  
wzc-->wangzhicheng
lc-->lichuang
jsf-->jisaifu
public class ForeachDemo02{
    public static void main(String args[]){
        Map<String,String> map = null; // 声明Map对象,其中key和value的类型为String
        map = new HashMap<String,String>() ;
        map.put("lc", "lichuang");      // 增加内容
        map.put("jsf", "jisaifu");      // 增加内容
        map.put("wzc", "wangzhicheng");     // 增加内容
        for(Map.Entry<String,String> me:map.entrySet()){
            System.out.println(me.getKey() + " --> " + me.getValue()) ;
        }
    }
}

如果要使用一个自定义的对象表示Map中的key,则对象所在类中一定要覆写equals()和hashCode()方法,否则无法找到对应的value。

class Person{
    private String name ;
    private int age ;
    public Person(String name,int age){
        this.name = name ;
        this.age = age ;
    }
    public String toString(){
        return "姓名:" + this.name + ";年龄:" + this.age ;
    }
    public boolean equals(Object obj){
        if(this==obj){
            return true ;
        }
        if(!(obj instanceof Person)){
            return false ;
        }
        Person p = (Person)obj ;
        if(this.name.equals(p.name)&&this.age==p.age){
            return true ;
        }else{
            return false ;
        }
    }
    public int hashCode(){
        return this.name.hashCode() * this.age ;
    }
};
public class HashMapDemo08{
    public static void main(String args[]){
        Map<Person,String> map = null ;
        map = new HashMap<Person,String>() ;
        map.put(new Person("张三",30),"zhangsan");    // 增加内容
        System.out.println(map.get(new Person("张三",30))) ;
    }
}
上一篇 下一篇

猜你喜欢

热点阅读