黑马程序员---java集合与框架

来源:互联网 发布:pid控制算法和图解 编辑:程序博客网 时间:2024/06/05 08:12

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


>> List


。 Set  无序、不可重复,  List  有序、可以重复 

。ArrayList 底层是一个 Object[] ,   对于 XxxList 的遍历 可以使用 迭代器,也可以使用 for   例:
List l = new ArrayList() ;    
l.add(123) ;
l.add(321) ;
l.add("kingowe") ;
l.add("kongchao") ;
for(int i=0; i<l.size(); i++)
{
  System.out.println(l.get(i) ) ;
}


。在 Arrays 工具类中有一个方法 asList(T... a) ) 可以将一个 数组转换成一个 List(ArrayList) 集合,可以方便对数组的操作,
但是不可以使用 List集合中的 增加 删除 等操作,因为数组长度是固定的, 使用了 这些方法 会 抛出异常

|--ArrayList:底层的数据结构是数组,线程不同步,ArrayList替代了Vector,查询元素的速度非常快。


|--LinkedList:底层的数据结构是链表,线程不同步,增删元素的速度非常快。



》》--》》   对 迭代器 iterator 的详解: 

package com.kingowe;import java.util.* ;import java.util.AbstractList.Itr;public class CollectionTest01 {public static void main(String[] args) {Collection c = new ArrayList() ;c.add(7) ;c.add(new Float(3.14)) ;c.add(true) ;c.add("kingowe") ; Iterator it = c.iterator() ;   // 相当于 Iterator it = new Itr() ;  /*    迭代器的源码 * public Iterator<E> iterator() {return new Itr();   } */while( it.hasNext() ){System.out.println(it.next());}}}/*  * Itr 类的实现,对迭代器对象 iterator 的创建 其实是创建的 private class Itr 的实例对象 *  private class Itr implements Iterator<E> {int cursor = 0;int lastRet = -1;int expectedModCount = modCount;public boolean hasNext() {            return cursor != size();}public E next() {            checkForComodification();    try {E next = get(cursor);lastRet = cursor++;return next;    } catch (IndexOutOfBoundsException e) {checkForComodification();throw new NoSuchElementException();    }}public void remove() {    if (lastRet == -1)throw new IllegalStateException();            checkForComodification();    try {AbstractList.this.remove(lastRet);if (lastRet < cursor)    cursor--;lastRet = -1;expectedModCount = modCount;    } catch (IndexOutOfBoundsException e) {throw new ConcurrentModificationException();    }}final void checkForComodification() {    if (modCount != expectedModCount)throw new ConcurrentModificationException();}    } *  *//* * 类关系继承图 * * public abstract class AbstractCollection<E>   implements Collection<E>  * * public abstract class AbstractList<E>   extends AbstractCollection<E>    implements List<E>  *  * public interface List<E>   extends Collection<E> *  * public class ArrayList<E>    extends AbstractList<E>        implements List<E>, RandomAccess, Cloneable, java.io.Serializable               */

。 对于 List 的实现类 有一个 ListIterator 迭代器, 它可以完成 对 List 的实现类 在迭代过程中的 增删改查 操作,
对于 Iterator 迭代器 如果在迭代过程中 对元素进行了修改 将会 抛出 CurrentModifierException, 但是使用
ListIterator 不会,ListIterator li = list.listiterator() ;


。使用 Iterator 迭代器 和 使用 ListIterator 迭代器时,在 使用它们的 next() 遍历集合中的元素的时候 指针会后移,
比如 ArrayList 集合中存放了 "孔超" "kingowe" "20", 当第一次使用 next() 后 指针会后移到 "kingowe"



》》--》》  对 contains 方法的详解


package com.kingowe;import java.util.* ;class Demo{String name ;int no ;public Demo(String name, int no){this.name = name ;this.no = no ;}}class Person{String name ;int age ;public Person(String name, int age){this.name = name ;this.age = age ;}public boolean equals(Object o){if(this == o)return true ;if(o instanceof Person){Person p = (Person)o ;if( p.name.equals(this.name) && p.age==this.age )return true ;}return false ;}}public class CollectionTest01 {public static void main(String[] args) {Collection c = new ArrayList() ;  // 如果这里换成 XxxSet 以下结果将为 true  false  true false// Set 无序、不可重复, List  有序、可以重复 。Demo d1 = new Demo("kongchao", 141) ;c.add(d1) ;System.out.println(c.contains(d1));  // trueDemo d2 = new Demo("kongchao", 141) ;System.out.println(c.contains(d2));   // false   在 Demo 类中没有重写 equals 方法,所以结果为 falsePerson p1 = new Person("kingowe", 20) ;c.add(p1) ;System.out.println( c.contains(p1) ) ;  // truePerson p2 = new Person("kingowe", 20) ;System.out.println( c.contains(p2) );   // true  Person类重写了 equals 方法,所以结果为 true}}/*   对 contains 方法的实现 * public boolean contains(Object o) {  // 在以上程序中传入的是 d1 与 d2,即为 Object o = b1, 或者 Object o = b2return indexOf(o) >= 0;    }    public int indexOf(Object o) {if (o == null) {  // 这里  如果传入的对象引用为 null, 那么在 ArrayList中查找是否有 null这个元素,     for (int i = 0; i < size; i++)if (elementData[i]==null)    return i;} else {    for (int i = 0; i < size; i++)if (o.equals(elementData[i]))  // 这里调用了 当前传入的对象的 equals 方法, 如果该对象所属<span style="white-space:pre"></span>   //的类没有 重写 equals 方法,则会调用 Object 中的 equals 方法    return i;}return -1;    } */

>> Set

。Set接口中的方法和Collection中方法一致的。Set接口取出方式只有一种,迭代器。

》!*!*!*!》  存储于集合中的对象都要重写 equals 方法, 存放在 HashSet 或存放在 HashMap中的key位置的对象 要重写
equals方法 和 hashCode 方法(HashMap中的key也是 Set --> 无序不可以重复)   例:




public class Employee
{
    String name ;
    String no ;
    public Employee(String name, String no)
    {
this.name = name ;
this.no = no ;
    }
}


Set s = new HashSet() ;
Employee e1 = new Employee("kingowe", 130141) ;
Employee e2 = new Employee("kingowe", 130141) ;
s.add(e1) ;
s.add(e2) ;
System.out.println(s.size()) ;  // 在 Employee 类 没有重写 hashCode 和 equals 方法时 输出结果为 2


解释: 因为 new 了 两个Employee 对象,虽然是同一个人,但是 HashCode 的值却不相等, 在执行 add() 方法时,会先
比较 要添加的对象的 HashCode 值 与 已经添加的对象的 hashCode 的值是否一样,如果不一样将会直接加进
该集合中,如果hashCode值与集合中已经添加的某个对象的 hashCode 的值相等,将会调用equals方法,
所以 要将 hashCode 方法 与 equals 方法重写


在本例中的 hashCode方法 的重写可以根据每个人的编号来重写,因为编号是 String 类的,且String类已经重写了
hashCode方法,所以可以  public int hashCode(){ return no.hashCode() ; }
hashCode 值 即为该对象在集合中存放的位置的索引


。 HashSet集合保证元素唯一性:通过元素的hashCode方法,和equals方法完成的。

当元素的hashCode值相同时,才继续判断元素的equals是否为true。
如果为true,那么视为相同元素,不存。如果为false,那么存储。
如果hashCode值不同,那么不判断equals,从而提高对象比较的速度。

· 对于ArrayList集合,判断元素是否存在,或者删元素底层依据都是equals方法。
· 对于HashSet集合,判断元素是否存在,或者删除元素,底层依据的是hashCode方法和equals方法。


》》--》》  TreeSet implements  SortedSet<E> 


。TreeSet集合中的元素是不可重复的,但是所有的元素会根据大小来排序,如果添加的是 基本数据类型对象,String类对象,或者 Date类
对象,那么遍历时会按大小顺序进行遍历输出, 因为这些类都实现了 Comparable 接口中的 compareTo 方法,但是如果添加的是
自定义类 而且没有实现 Cpmparable 接口 在运行时将会出现 ClassCastException


。 在向 TreeSet 集合中 add 元素的时候 会调用 compareTo 方法, 如果在实现 compareTo 方法的时候 直接 return 0 ; 那么执行 add
方法 无论 add 多少个元素 只能将第一次 add 的 对象添加进去, 因为 return 0; 表示 所添加的元素 相等,Set 不允许重复


。 TreeSet底层的数据结构就是二叉树。

package com.kingowe;public class Demo1 {private double price ;public Demo1(){}public Demo1(double price){this.price = price ;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {      //  不要忘了Override toString 方法return "Demo1 [price=" + price + "]";}}package com.kingowe;import java.util.Comparator;// 专用于 Demo1 的比较器public class Demo1Comparator implements Comparator {/*在 java.util.Comparator 接口中定义了 两个方法: * boolean equals(Object obj)   *  int compare(T o1, T o2)  *  因为 所有类都继承自 Object, 在 Object 中已经有了 equals 方法 *  所以本类中已经有了继承自 Object类的 equals方法 *  因此  如果在该类中用不到  equals 方法,则可以只重写 compare 方法 *  如果一个非abstract类只重写了一个接口中的部分方法,那么别的方法一定 *  已经在他的 父类 中实现了 */@Overridepublic int compare(Object o1, Object o2) {double price1 = ( (Demo1)o1 ).getPrice() ;double price2 = ( (Demo1)o2 ).getPrice() ;if(price1 > price2){return 1 ;}else if(price1 < price2){return -1 ;}else return 0 ;}/*  * 注意: 在此程序中 对 double 类型的比较设计的不合理,因为double型在 * 内存中存储时是按近似值存储的,因此有可能出现 两个价格都为17.17 却不会 * 返回  0 */}package com.kingowe;import java.util.* ;public class TreeSetTest {public static void main(String[] args) {// TreeSet(Comparator<? super E> comparator)//  通过传入一个比较器来完成 add时对象之间的比较SortedSet ss = new TreeSet(new Demo1Comparator()) ;ss.add(new Demo1(34.5)) ;ss.add(new Demo1(12.3)) ;ss.add(new Demo1(67.8)) ;ss.add(new Demo1(45.6)) ;ss.add(new Demo1(33.4)) ;ss.add(new Demo1(56.7)) ;Iterator it = ss.iterator() ;while(it.hasNext()){System.out.println(it.next());}}}

>> Map

。 存储在 Map集合 中的 key 值元素要重写 equals 方法 和 hashCode 方法,如果 key 值是String类型,则可以不重写,
因为在 String 类中已经重写了这两个方法


。 Set<K> keySet()  因为 key 值不可以重复,所以要返回 Set ,   Collection<V> values()  因为 vlaue 值可以重复,所以
要返回 Collection

。 |--Hashtable:底层是哈希表数据结构,是线程同步的。不可以存储null键,null值。
   |--HashMap:底层是哈希表数据结构,是线程不同步的。可以存储null键,null值。替代了Hashtable.

  values 方法解释: 

package com.kingowe;import java.util.*;public class MapTest {public static void main(String[] args) {Map m = new HashMap();m.put("1000", "kingowe");m.put("1001", "kongchao");Collection c = m.values() ;Iterator it = c.iterator() ;  while(it.hasNext()){    System.out.println(it.next()) ;}    System.out.println(c.size());    System.out.println(c.isEmpty());}}java.util.HashMap 中 values() 的源码:public Collection<V> values() {        Collection<V> vs = values;        return (vs != null ? vs : (values = new Values()));}// AbstractCollection<E>定义:  public abstract class AbstractCollection<E> implements Collection<E> // 属性 values 的声明 : transient volatile Collection<V> values = null;        // Values  内部类    private final class Values extends AbstractCollection<V> {        public Iterator<V> iterator() {            return newValueIterator();        }        public int size() {            return size;        }        public boolean contains(Object o) {            return containsValue(o);        }        public void clear() {            HashMap.this.clear();        }    }
》》--》》  遍历 Map 中的 key - value

/方法一(通常使用该方法,比较灵活):

package com.kingowe;import java.util.*;public class MapTest {public static void main(String[] args) {Map m = new HashMap();m.put("1000", "kingowe");m.put("1001", "kongchao");m.put("1005", "kong");m.put("1002", "king");Set s = m.keySet() ;   // 通过该方法获得 Map集合 中的 key值 的 Set集合Iterator it = s.iterator() ;   // 获得 set 集合的迭代器,while(it.hasNext()){Object k = it.next();   // 取出 Map集合中的 key 值Object v = m.get(k) ;   // 通过得到的 key 值 来获取相对应的 valueSystem.out.println(k+" --> "+v);    // 最后将 key - value 对输出}}}
方法二(不灵活,输出格式只能是 key=value):

package com.kingowe;import java.util.*;public class MapTest {public static void main(String[] args) {Map m = new HashMap();m.put("1000", "kingowe");m.put("1001", "kongchao");m.put("1005", "kong");m.put("1002", "king");// 通过 Set entrySet() 来获取 key=value  Set s = m.entrySet() ;Iterator it = s.iterator() ;while(it.hasNext()){System.out.println(it.next());}}}





0 0