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

------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));  // true
		Demo d2 = new Demo("kongchao", 141) ;
		System.out.println(c.contains(d2));   // false   在 Demo 类中没有重写 equals 方法,所以结果为 false
		
		Person p1 = new Person("kingowe", 20) ;
		c.add(p1) ;
		System.out.println( c.contains(p1) ) ;  // true
		Person 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 = b2
	return 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;
	}
	@Override
	public 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类只重写了一个接口中的部分方法,那么别的方法一定
 *  已经在他的 父类 中实现了
 */

	@Override
	public 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 值 来获取相对应的 value
			System.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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值