java note 7集合

集合部分的继承关系要把常用的类(接口)搞清楚。这一章笔记只包括常用的类。

interface iterable
interface Collection
interface List
interface Set
ArrayList
LinkedList
Vector
HachSet
interface SortedSet
TreeSet
interface Map < key,value >
HashMap
HashTable
interface SortedMap
Properties
TreeMap

Collection

集合只能存储引用类型。

  • List:有序,可重复
  • Set:无序,不重复
  • Map:无序键值对,键不可重复,值可重复。

List和Set继承自Collection接口

java.util.Collection<E>接口
单个存储!!!!!!
<>是泛型。

java.util.Iterator接口主要有hasNext(),next(),remove(),1.8又加了forEachRemaining()

重点实现类:

  • ArrayList, LinkedList
  • HashSet, TreeSet.
  • SortedSet:无序,不重复,但取出时可按元素大小排序。

常用集合类底层数据结构

  • ArrayList:数组,适合查询,不适合频繁增删元素。常用。
  • LinkedList:双向链表。
  • Vector:数组,但是线程安全。但效率低,很少使用。采用其它方式实现线程安全。

重要方法:

add, clear, contains, isEmpty, iterator, remove, size, toArray.

注意Collection没有get()方法。

import java.util.*;

public class CollectionTest01{
	
	public static void main(String[] args){
		Collection c = new ArrayList();

		c.add(1);
		c.add("a");

		Person p1 = new Person("Tom",12);

		c.add(p1);

		System.out.println("c.size(): "+c.size());
		System.out.println("c.isEmpty(): "+c.isEmpty());

		//c.remove(p1);
		System.out.println("c.contains(p1): "+c.contains(p1));



		Object[] objs = c.toArray();
		for(int i=0;i<objs.length;i++){
			System.out.println(objs[i]);
		}

		c.clear();
		System.out.println("after c.clear()... ");
		objs = c.toArray();
		for(int i=0;i<objs.length;i++){
			System.out.println(objs[i]);
		}
	}
}
class Person{
	String name;
	int age;

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

	public String toString(){
		return "Person[name="+name+",age="+age+"]";
	}
}

迭代

iterator()来自于Iterable接口,用于获取集合所依赖的迭代器对象(ListItr,AbstractListItr,并包含内部类),是所有集合通用的遍历方式。
详细继承关系查询api

contains()remove()底层调用了equals().
所以存储在集合中的元素应该重写equals()方法。

删除要使用迭代器的remove(),因为使用集合的remove()会改变集合c进而导致迭代器error.

import java.util.*;

public class CollectionTest02{
	
	public static void main(String[] args){
		Collection c = new ArrayList();

		c.add(1);
		c.add("a");

		Iterator itr = c.iterator();

		System.out.println(itr);  //java.util.ArrayList$Itr@15db9742
		System.out.println(c);

	}
}
import java.util.*;

public class CollectionTest03{
	
	public static void main(String[] args){
		Collection c = new ArrayList();

		Integer i1 = new Integer(1);
		c.add(i1);
		
		Integer i2 = new Integer(1);

		System.out.println(c.contains(i2));  //true

		c.remove(i2);
		System.out.println(c.size());	//0

		Person p1 = new Person("Tom",12);
		c.add(p1);

		Person p2 = new Person("Tom",12);
		System.out.println(c.contains(p2));  //true

		c.remove(p2);
		System.out.println(c.size());	//0
	}
}
class Person{
	String name;
	int age;

	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==this.name && p.age==this.age){
				return true;
			}
		}

		return false;
	}
}

List

import java.util.*;

public class ListText01{
	@SuppressWarnings("unchecked")
	public static void main(String[] args){
		
		//List l = new ArrayList();
		//ArrayList<Integer> l = new ArrayList<Integer>();
		//List<Integer> l = new ArrayList<Integer>();
		List<Integer> l = new LinkedList<Integer>();

		l.add(1);
		l.add(2);
		l.add(3);
		l.add(3);

		Iterator itr = l.iterator();
		while(itr.hasNext()){
			//Object o = itr.next();
			System.out.println(itr.next());
		}

		for(int i=0;i<l.size();i++){
			System.out.println(l.get(i));
		}
		System.out.println(l);
	}
}

ArrayList默认容量是10,扩容后是原来的1.5倍。
LinkedList没有容量。
Vector默认容量是10,扩容后是原来的1.5倍。

注意add()是插入,不是替换。

优化ArrayListVector,可以通过预测并指定初始化容量,减少扩容(数组拷贝)。

##Set

###HashSet

HashSet其实就是HashMap的key部分。
两类初始容量都是16.

HashMap类中有static final float DEFAULT_LOAD_FACTOR = 0.75;
扩容因子,意思是数组装满75%则扩容。

import java.util.*;

public class SetTest01{
	public static void main(String[] args){
		Set<Integer> s = new HashSet<Integer>();

		s.add(1);
		s.add(2);
		s.add(3);
		s.add(3);

		Iterator itr = s.iterator();
		while(itr.hasNext()){
			System.out.println(itr.next());
		} 
	}
}

java.lang.Object.hashCode()
总之Object的方法都是用来重写的。

存储在HashSetHashMap中的元素需要同时重写HashCode()equals().

import java.util.*;

public class SetTest02{
	public static void main(String[] args){
		Set<Employee> s = new HashSet<Employee>();

		Employee e1 = new Employee("1000","Tom");
		Employee e2 = new Employee("1000","Tom");
		Employee e3 = new Employee("2000","Jerry");
		Employee e4 = new Employee("3000","John");

		s.add(e1);
		s.add(e2);
		s.add(e3);
		s.add(e4);

		Iterator itr = s.iterator();
		while(itr.hasNext()){
			System.out.println(itr.next());
            /*
                Employee@17005f
                Employee@1774be
                Employee@17e91d
            */
		} 
		System.out.println(e1.hashCode());
		System.out.println(e2.hashCode());
		System.out.println(s.size());
        /*
            1507423
            1507423
            3
        */
	}
}

class Employee{

	//1000-9999
	String no;

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

	public boolean equals(Object o){
		if(this == o) return true;
		if(o instanceof Employee){
			Employee e = (Employee)o;
			if(e.no.equals(this.no) && e.name.equals(this.name)){
				return true;
			}
		}
		return false;
	}


	public int hashCode(){

		//String.hashCode()
		return no.hashCode();
	}

}

SortedSet

实现类有TreeSet

Integer,String,Date都实现了接口java.lang.Comparable的compareTo(),所以可比较。
o1.compareTo(o2)

import java.util.*;
import java.text.SimpleDateFormat;
import java.text.ParseException;

public class SortedSetTest{
	public static void main(String[] args) throws ParseException{

		SortedSet<Integer> ss = new TreeSet<Integer>();

		ss.add(3);
		ss.add(2);
		ss.add(5);
		ss.add(1);

		Iterator itr1 = ss.iterator();
		while(itr1.hasNext()){
			Object o = itr1.next();
			System.out.println(o);
		}


		SortedSet<String> ss2 = new TreeSet<String>();

		ss2.add("John");
		ss2.add("Jerry");
		ss2.add("Tom");
		ss2.add("Cris");

		Iterator itr2 = ss2.iterator();
		while(itr2.hasNext()){
			Object o = itr2.next();
			System.out.println(o);
		}


		SortedSet<Date> ss3 = new TreeSet<Date>();

		String st1 = "2012-01-03";
		String st2 = "2010-07-01";
		String st3 = "2008-08-08";
		String st4 = "2012-12-12";

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

		Date d1 = sdf.parse(st1);
		Date d2 = sdf.parse(st2);
		Date d3 = sdf.parse(st3);
		Date d4 = sdf.parse(st4);

		ss3.add(d1);
		ss3.add(d2);
		ss3.add(d3);
		ss3.add(d4);

		Iterator itr3 = ss3.iterator();
		while(itr3.hasNext()){
			Object o = itr3.next();
			System.out.println(o);
		}


	}
}

import java.util.*;

public class CompTest{
	public static void main(String[] args){

		SortedSet<Person> ss = new TreeSet<Person>();

		Person p1 = new Person("Tom",12);
		Person p2 = new Person("Jack",10);
		Person p3 = new Person("Ann",14);
		Person p4 = new Person("Cris",11);
		Person p5 = new Person("Conner",13);

		ss.add(p1);
		ss.add(p2);
		ss.add(p3);
		ss.add(p4);
		ss.add(p5);

		Iterator itr = ss.iterator();
		while(itr.hasNext()){
			System.out.println(itr.next());
		}
	}
}

class Person implements Comparable{
	String name;
	int age;

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

	public String toString(){
		return "Person[name="+name+",age="+age+"]";
	}

	public int compareTo(Object o){
		/*
		int age1 = this.age;
		int age2 = ((Person)o).age;
		return age1-age2;
		*/
		String s1 = this.name;
		String s2 = ((Person)o).name;
		return s1.compareTo(s2);
	}
}

注意Comparable<T>,显示支持泛型。

实现java.lang.Comparable<T>.compareTo()是第一种方式,另一种方式是java.util.Comparator比较器接口,需要重写compare()方法。

import java.util.*;

public class ComparatorTest{
	public static void main(String[] args){

		SortedSet<Product> products = new TreeSet<Product>(new ProductComparator());

		/*
		//anonymous inner class
		SortedSet<Product> products = new TreeSet<Product>(new ProductComparator(){
			public int compare(Object o1,Object o2){
				double price1 = ((Product)o1).price;
				double price2 = ((Product)o2).price;

				if(price1==price2){
					return 0;
				}else if(price1>price2){
					return 1;
				}else{
					return -1;
				}
			}
		});
		*/

		Product p1 = new Product(12);
		Product p2 = new Product(10);
		Product p3 = new Product(14);
		Product p4 = new Product(11);
		Product p5 = new Product(13);

		products.add(p1);
		products.add(p2);
		products.add(p3);
		products.add(p4);
		products.add(p5);

		Iterator itr = products.iterator();
		while(itr.hasNext()){
			System.out.println(itr.next());
		}
	}
}

class Product{
	double price;

	Product(double 	price){
		this.price = price;
	}

	public String toString(){
		return price+"";
	}
}


class ProductComparator implements Comparator{
	public int compare(Object o1,Object o2){
		double price1 = ((Product)o1).price;
		double price2 = ((Product)o2).price;

		if(price1==price2){
			return 0;
		}else if(price1>price2){
			return 1;
		}else{
			return -1;
		}
	}
}

TreeSet有这样一种构造方法:TreeSet(Comparator<? super E> comparator)
采用了匿名内部类,不推荐,因为这种比较器无法重复利用。

优先选耦合度低的比较器方式。


Map

Map接口实现类:
HashMap, Hashtable,SortedMap.

HashMapKey等同于一个Set集合

Hashtable线程安全。但效率低,很少使用。但它有一个重要的类Properties,该类的keyvalue只能是字符串类型。

SortedMapKey也等同于一个Set集合

单向链表:节点Entry entry;

双向链表:java.util.LinkedList

存储在Map集合key部分的元素需要重写hashCode()equals()方法。

如果key重复,则value会覆盖。

HashMap

java.util.HashSet,底层是HashMap.
HashMap底层是Entry类型数组,即哈希表。

哈希表:单向链表的数组。
类似于字典。增删查询效率都很高。

Entry是链表类(api),每个节点都有一个final int hash.
单向链表中每一个节点的hash值是相同的,是Object key经过hashCode()得到的,代表数组下标。
Object get(Object key)

import java.util.*;

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

		persons.put("1000","Tom");
		persons.put("1000","Jack");
		persons.put("1001","Tom");
		persons.put("2000","Jerry");
		persons.put("3000","John");
		
		Collection values = persons.values();
		Iterator itr1 = values.iterator();
		while(itr1.hasNext()){
			System.out.println(itr1.next());
		}

		Set keys = persons.keySet();
		Iterator itr2 = keys.iterator();
		while(itr2.hasNext()){
			Object key = itr2.next();
			Object value = persons.get(key);
			System.out.println(key+"-->"+value);
		}

		Set entrySets = persons.entrySet();
		Iterator itr3 = entrySets.iterator();
		while(itr3.hasNext()){
			System.out.println(itr3.next());
		}
	}
}

向hash表中添加元素:
V put(Object key,Object value)
hashCode(key)得到hash值,
若hash表不存在该hash值,则直接加入元素到数组中。
若hash表存在该hash值,则用equals()遍历链表key,false则添加,true则放弃添加。

Hashtable

默认初始容量(11),负载因子(0.75)。
Properties的key和value都是String类型。

SortedMap

实现类有TreeMap

import java.util.*;

public class SortedMapTest{
	public static void main(String[] args){
		Map<Product,Double> products = new TreeMap<Product,Double>();

		Product p1 = new Product("apple",2.0);
		Product p2 = new Product("banana",1.0);
		Product p3 = new Product("orange",5.0);
		Product p4 = new Product("pear",4.0);
		Product p5 = new Product("peach",3.0);

		//value:kg
		products.put(p1,3.0);
		products.put(p2,4.0);
		products.put(p3,1.0);
		products.put(p4,2.0);
		products.put(p5,7.0);
		
		
		Set entrySets = products.entrySet();
		Iterator itr = entrySets.iterator();
		while(itr.hasNext()){
			System.out.println(itr.next()+"kg");
		}
		
		Set keys = products.keySet();
		Iterator itr2 = keys.iterator();
		while(itr2.hasNext()){
			Object k = itr2.next();
			Object v = products.get(k);
			System.out.println(k+"---"+v+"kg");
		}

	}
}

class Product implements Comparable{
	String name;
	double price;

	Product(String name,double price){
		this.name = name;
		this.price = price;
	}

	public String toString(){
		return "["+name+"---"+price+"]";
	}

	public int compareTo(Object o){
		
		double price1 = this.price;
		double price2 = ((Product)o).price;
		if(price1==price2){
			return 0;
		}else if(price1>price2){
			return -1;
		}else{
			return 1; 
		} 
		
		/*
		String s1 = this.name;
		String s2 = ((Product)o).name;
		return s1.compareTo(s2);
		*/
	}
}

SortedMap的key可以自动排序,需要实现Comparable接口,并单独写一个比较器。

Collections

Collections是一个类,而Collection是一个接口。

import java.util.*;

public class CollectionsTest{
	
	public static void main(String[] args){
		List c = new ArrayList();

		c.add(9);
		c.add(6);
		c.add(8);
		c.add(3);
		c.add(5);

		for(Iterator itr=c.iterator();itr.hasNext();){
			System.out.println(itr.next());
		}

		Collections.sort(c);
		System.out.println("---------------------------");
		for(Iterator itr=c.iterator();itr.hasNext();){
			System.out.println(itr.next());
		}

		Set s = new HashSet();

		s.add(9);
		s.add(6);
		s.add(8);
		s.add(3);
		s.add(5);
		
		System.out.println("---------------------------");
		List sl = new ArrayList(s);
		Collections.sort(sl);
		for(int i=0;i<sl.size();i++){
			System.out.println(sl.get(i));
		}

		c.clear();

		Person p1 = new Person("Tom",12);
		Person p2 = new Person("Jack",10);
		Person p3 = new Person("Ann",14);
		Person p4 = new Person("Cris",11);
		Person p5 = new Person("Conner",13);

		c.add(p1);
		c.add(p2);
		c.add(p3);
		c.add(p4);
		c.add(p5);

		System.out.println("---------------------------");
		for(Iterator itr=c.iterator();itr.hasNext();){
			System.out.println(itr.next());
		}

		Collections.sort(c);
		System.out.println("---------------------------");
		for(Iterator itr=c.iterator();itr.hasNext();){
			System.out.println(itr.next());
		}

		//secure threads
		//Collections.synchronizedList(c);

	}
}
class Person implements Comparable{
	String name;
	int age;

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

	public String toString(){
		return "["+name+"---"+age+"]";
	}

	public int compareTo(Object o){
		
		double age1 = this.age;
		double age2 = ((Person)o).age;
		if(age1==age2){
			return 0;
		}else if(age1>age2){
			return -1;
		}else{
			return 1; 
		} 
		
		/*
		String s1 = this.name;
		String s2 = ((Person)o).name;
		return s1.compareTo(s2);
		*/
	}
}

泛型

这是JDK5.0加入的特性,和自动拆装箱一样是编译器的特点。

为什么引入?

  • 统一集合中的数据类型
  • 减少强制类型转换(Object->其他类)

优点:同一类型,减少强制转换。
缺点:只能存储一种类型。

<E>指Element
<K,V>指键值对

List<String> strs = new ArrayList<Stirng>();
Iterator<String> it = strs.iterator();
while(it.hasNext()){
	String s = it.next;
}
//下面是不用泛型的情况
while(it.hasNext()){
	Object o = it.next();
	if(o instanceof String){
		String s = (String)o;
	}
}

注意实现Comparable接口的区别

自定义泛型
class MyClass<T>{}

__foreach__也是JDK5.0加入的特性

for(类型 变量:数组名/集合名)
集合需要用泛型
否则类型应该为Object

缺点:没有下标

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值