java基础_集合

 

1   集合概述:

 

 

1.1,为什么出现集合?

面向对象语言的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。

1.2,数组和集合类同是容器,有何不同?

数组虽然也可以存储对象,但长度是固定的,集合长度是可变的数组中可以存储基本数据类型,集合只能存储对象,

1.3,集合类的特点:

集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。

1.4,Collection的一些方法

Collection接口Collection接口是List和Set和Queue接口的父接口,该接口里定义的方法既可以 操作Set集合。

也可以用于操作List集合,所以我们要先学习一下Collection里的基本方法:


1、添加元素

        add(Objectobj); //add方法的参数类型是Object。以便于接收任意类型对象。

2、删除元素

        remove(Objectobj);

        removeAll(另一集合);//调用者只保留另一集合中没有的元素。

        clear();//清空集合

3、判断元素

        contains(Objectobj);//判断是否存在obj这个元素

        isEmpty();//是否为空

4、获取个数,集合长度

        size();

5、取交集

        retainAll(另一集合);//调用者只保留两集合的共性元素。

 


 

1.5集合元素的获取

当使用System.out的println方法来输出集合对象时,将输出[ele1,ele2,....]的形式,显然是因为所有的Collection实现类都重写了toString()方法但是如果想依次访问集合里的每一个元素,则需要使用某种方式来遍历集合对象,使用Iterator接口遍历集合对象或者使用foreach循环遍历集合元素。

 


注意在没有限定泛型时,我们把一个对象放进集合里,集合会忘记这个对象的类型,集合会把所有的元素当成Object类的实例进行处理。

1,使用Iterator接口(在迭代时,只能用迭代器的方法操作元素)

Iterator接口里定义了3个方法。

boolean hasNext();判断集合是否有下一个元素

E next();返回集合的下一个元素

void remove();删除集合里上一次next方法返回的元素

 

class IteratorTest
{
	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();
		al.add("java01");//add(Object obj);
		al.add("java02");
		al.add("java03");
		al.add("java04");
		Iterator it = al.iterator();//获取迭代器,用于取出集合中的元素。

		while(it.hasNext())
		{
			//it.next()方法返回的数据类型是Object类型。需要强制类型转换
			String s = (String)it.next();
			if(s.equals("java02"))
			{
				sop(s);
				it.remove();
				//s.remove("java02") ,使用Iterator迭代过程中,不可修改集合元素,否则引起java.util.ConcurrentModificationException异常。
			}
		}
	}
}

Iterator仅用于遍历集合,Iterator本身并不提供盛装对象的能力,如果需要创建Iterator对象,则必须有一个被迭代的集合。

 


2使用foreach循环

 

class IteratorTest 
{
	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();
		al.add("java01");//add(Object obj);
		al.add("java02");
		al.add("java03");
		al.add("java04");
		for(Object obj : al)
		{
			String s = (String)obj;
			System.out.println(s);
			if(s.equals("java02"))
			{
				//ad.remove(s);引发异常
			}
		}
	}
}

 


2  List集合

2.1,List的特点:

|--List:元素是有序的,元素可以重复,因为该集合体系有索引。
|--ArrayList;底层的数据结构使用的是数组结构。特点:查询速度快,但是增删慢。线程不同步(默认长度10 )
|--LinkedList;底层使用的是链表数据结构。   特点:增删速度很快,查询稍慢。
|--Vector;    底层是数组数据结构   线程同步。被ArrayList替代了。

 

2.2,List的特有方法:凡是可以操作操作角标的方法都是该体系特有的方法。

1、增

        booleanadd(index,element);//指定位置添加元素

        BooleanaddAll(index,Collection);//在指定位置增加给定集合中的所有元素,若省略位置参数,则在当前集合的后面依次添加元素

2、删

        Booleanremove(index);//删除指定位置的元素

3、改

        set(index,element);//修改指定位置的元素。

4、查

        get(index);//通过角标获取元素

        subList(from,to);//获取部分对象元素

5、其他

        listIterator();//List特有的迭代器

        indexOf(obj);//获取元素第一次出现的位置,如果没有则返回-1

 


注意:当调用List的set(index,Elements)方法来改变List集合索引处的元素时,指定的索引必须是List集合的有效索引.
例如集合长度为4,就不能指定替换索引为4处的元素。


扩展:List集合可以根据位置索引来访问集合中的元素,因此List增加了一种新的遍历集合元素的方法:使用普通的for循环来遍历集合元素。
class ForTest
{
	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();
		//1,添加元素。
		al.add("java01");//add(Object obj);
		al.add("java02");
		al.add("java03");
		al.add("java04");
		for(int x= 0; x<al.size();x++)
		{
			System.out.println("al("+x+")="+al.get(x));
		}
	}
}


2.3,List_equals():


注意:List判断两个对象相等只要通过equals()方法比较返回true即可。(contains(),remove(),indexOf(),等方法都会自动调用equals()方法)。
所以在将一个对象存进List集合里时,复写其equals()方法,是非常有必要的。

练习(List_equals复写)将自定义对象作为元素存到ArrayList集合中,并去除重复元素。

比如:存人对象。同姓名同年龄,视为同一个人。为重复元素。
class Person
{
	private String name;
	private int age;
	Person(String name, int age)
	{
		this.name = name;
		this.age = age;
	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
	public boolean equals(Object obj)//自动被调用
	{
		if(!(obj instanceof Person))
			return false;

		Person p = (Person)obj;
		System.out.println(this.name+"........"+p.name);

		return this.name.equals(p.name) && this.age == p.age;
	}
}
class ArrayListTest2 
{
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();
		al.add(new Person("lisi01",30));//al.add(Object obj);//Object obj = new Person("lisi01",30;)
		al.add(new Person("lisi02",32));
		al.add(new Person("lisi03",33));
		al.add(new Person("lisi04",35));

		//al = singleElements(al);
		sop("remove 03:"+al.remove(new Person("lisi03",33)));//需要用到判断,所以要写equals()方法。返回true

		Iterator it = al.iterator();
		while(it.hasNext())
		{
			
			Person p = (Person)it.next();//做强制转换。it.next是Object类型的,不认识getName()方法。所以要做强制转化
			sop(p.getName()+"::"+p.getAge());
		}
	}
	public static ArrayList singleElements(ArrayList al)
	{
		//定义一个临时容器。
		ArrayList newal = new ArrayList();
		Iterator it = al.iterator();

		while(it.hasNext())
		{
			Object obj = it.next();

			if(!newal.contains(obj))//底层自动调用equals()方法,obj调用自身的equals的方法,和newal的各个元素进行比较
				newal.add(obj); 
		}
		return newal;
	}
}


2.4,List_listIterator()

List还额外提供了一个listIterator()方法,返回一个ListIterator对象,提供了专门操作List的方法。在listIterator接口基础上增加了如下方法。

->boolean hasPrevious();返回该迭代器关联的集合是否有上一个元素。
->Object previous();返回该迭代器的上一个元素。
->void add();在指定位置插入一个元素。

 

2.5,linkedList

 
linkedList的特有方法
1,添加元素
addFirst();
addLast();

2,获取元素但不删除元素。如果集合中没有元素,会出现异常。NoSuchElementException
getFirst();
getLast();

3获取元素,并删除元素。如果集合中没有元素,会出现异常。
removeFirst();
removeLast();

在JDK1.6出现了替代方法。
1,添加元素
offerFirst();
offerLast();
获取元素但不删除元素。如果集合中没有元素,会返回null
peekFirst();
peekLast();

获取元素,并删除元素。如果集合中没有元素,会返回null
pollFirst();
pollLast();

2.练习(LinkedList)

例:使用LinkedList模拟一个队列或者其他数据结构。
import java.util.*;
class DuiLie
{
	private LinkedList link;
	DuiLie()
	{
		link = new LinkedList();
	}
	public void myAdd(Object obj)
	{
		link.addFirst(obj);
	}
	public Object myGet()
	{
		return link.removeLast();
	}
	public boolean isNull()
	{
		return link.isEmpty();
	}
}
class  LinkedListTest
{
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		DuiLie dl = new DuiLie();		dl.myAdd("java01");
		dl.myAdd("java02");
		dl.myAdd("java03");
		dl.myAdd("java04");

		while(!dl.isNull())
		{
			sop(dl.myGet());
		}
	}	
}

3 Set集合

3.1Set集合特点

|--Set:元素师无序(存入和取出的顺序不一定一致),元素不可以重复。元素值可以是null(只有一种取出方式迭代器。)
|--HashSet:底层数据结构是哈希表。线程不是同步的。
|--TreeSet:底层数据结构是二叉树。可以对Set集合中的元素进行排序。

3.2HashSet

元素的唯一性是通过元素的两个方法,hashCode和equals来完成。

1,如果元素的HashCode(存放位置)值相同,才会判断equals(对象本身)是否为true
2,如果元素的Hashcode值不同,不会调用equals。
hashcode()一样,equals()不一样也存得进去。(在同一个位置,以链的方式存储)

注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的HashCode和equals方法。

(set集合的方法和Colletion接口是一致的。)

练习:HashSet_HashCode() and equals()

例:往HashSet集合中 存入自定对象。
姓名和年龄相同视为同一个人,重复元素。
class HashSetTest 
{
	public static void main(String[] args) 
	{
		HashSet hs = new HashSet();
		hs.add(new Person("a1",11));
		hs.add(new Person("a2",12));
		hs.add(new Person("a3",13));
		hs.add(new Person("a2",12));
			//先算一下new Person("a1",12);的hashcode值,和hs里的a2一样,就调用自身的equals()方法。
		hs.remove(new Person("a3",13));
		Iterator it = hs.iterator();
		
		while(it.hasNext())
		{
			Person p =(Person)it.next();
			sop(p.getName()+":;"+p.getAge());
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
class Person
{
	private String name;
	private int age;
	Person(String name, int age)
	{
		this.name = name;
		this.age = age;
	}
	public int hashCode()//复写哈希值使equals运行。
	{
		System.out.println(this.name+" .....hashcode")
		return name.hashCode()+age;
	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
	public boolean equals(Object obj)
	{
		if(!(obj instanceof Person))
			return false;
		Person p = (Person)obj;
		System.out.println(this.name+"....equals...."+p.name);
		/*
		a2...equals..a1
		a3...equals..a2
		a3...equals..a1
		a2...equals..a3
		a2...equals..a2
		*/
		return this.name.equals(p.name) && this.age==p.age;
	}	
}


3.3TreeSet

保证元素唯一性的依据。compareTo方法return 0.

3.3.1TreeSer排序的第一种方式:

让元素自身具备比较性。
元素需要实现Comparable接口,覆盖compareTo方法。
这种方式也称为元素的自然顺序,或者默认顺序。

3.3.2TreeSet的第二种排序方式。

当元素自身不具备比较性,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性,在集合初始化时,就有了比较性。
定义了比较器,实现Comparator接口,覆盖compare方法,将比较器对象作为参数传递给TreeSet集合的构造函数。

当两种排序都存在时,以比较器为主。

练习(TreeSet排序):往TreeSet存入自定义对象学生

想按照学生的年龄进行排序。
(往TreeSet存储的对象都要具备计较性。)
记住:排序时,当主要条件相同时,一定要判断一下次要条件。
class TreeSetDemo 
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet();
		//将自定义的比较器传给TreeSet的构造器
		//TreeSet ts = new TreeSet(new MyCompare());
		ts.add(new Student("lisi02",22));
		ts.add(new Student("lisi07",20));//07存进来的时候,调用自己的compareTo和02比较
		//没有实现comparable接口会Student cannot be cast to java.lang.Comparable 
		ts.add(new Student("lisi09",19));//09存进来的时候,调用自己的compareTo分别和02,07比较。
		ts.add(new Student("lisi01",40));

		Iterator it = ts.iterator();
		while(it.hasNext())
		{
			Student stu = (Student)it.next();
			System.out.println(stu.getName()+"....."+stu.getAge());
		}
	}
}
class Student implements Comparable //该接口强制让学生具备比较性。
{
	private String name;
	private int age;

	Student(String name, int age)
	{
		this.name = name;
		this.age = age;
	}
	public int compareTo(Object obj)
	{
		if(!(obj instanceof Student))
			throw new RuntimeException("不是学生对象")
		Student s = (Student)obj;
		if(this.age>s.age)
			return 1;
		if(this.age==s.age)
		{
			return this.name.compareTo(s.name);
		}
		return -1;		
	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age
	}
}
//当元素自身不具备比较性,或者具备的比较性不是所需要的。
//这时需要让容器自身具备比较性。
//定义了比较器,实现Comparator接口,覆盖compare方法,将比较器对象作为参数传递给TreeSet集合的构造函数
class MyCompare implements Comparator//两个对象被集合比。。
{
	public int compare(Object o1,Object o2)
	{
		Student s1 = (Student)o1;
		Student s2 = (Student)o2;

		
		int num = s1.getName().compareTo(s2.getName());//(String已经实现了Comparator)
	
		if(num==0)//主条件相同判断次要条件。 
		{	 
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		}
		return num;
	}
}

4Map集合

4.1Map集合特点

Map集合:该集合存储键值,,一对一对往里存。而且要保证键的唯一性。

|--Hashtable:底层是哈希表数据结构,不可以存入null键null值集合式线程同步的。
用作键的对象必须实现equals()和hashcode()方法。
|--HashMap:底层是哈希表数据结构,并允许使用null值和null值,该集合是不同步的。
|--TreeMap:底层是二叉树数据结构。线程是不同步。可以用于给Map集合中的键排序。

注意:其实,Set集合底层就是使用了Map集合。
(Map提供了一个Entry内部类来封装key-value对,而计算Entry存储时只考虑Entry封装的key,从java源码来看,java
是先实现了Map,然后通过包装一个所有vanlue都为null的Map就实现了Set集合)

4.2Map接口常用方法。

1、添加

        Vput(K key,V value);//添加元素,如果出现添加时,相同的键,那么后添加的值会覆盖原有键对应值,并put方法会返回被覆盖的值。

        voidputAll(Map <? extends K,? extends V> m);//添加一个集合

2、删除

        clear();//清空

        Vremove(Object key);//删除指定键值对

3、判断

        containsKey(Objectkey);//判断键是否存在

        containsValue(Objectvalue)//判断值是否存在

        isEmpty();//判断是否为空

4、获取

        Vget(Object key);//通过键获取对应的值

        size();//获取集合的长度

        Collection<V>value();//获取Map集合中所以得值,返回一个Collection集合

5,,两个关于取出的方法

        Set<Map.Entry<K,V>>entrySet();返回该Map中所有key组成的Set集合。

        Set<K>  keySet();返回该Map中包含的key-value对所组成的Set集合,每个集合元素都是Map.Entry对象。

注:HashMap集合可以通过get()方法的返回值来判断一个键是否存在,通过返回null来判断。

 

-
4.3map集合的两种取出方式

1,Set<k> keySet;将map中所有的键存入到Set集合,因为Set具备迭代器,
所以可以通过迭代方式取出所有的键,再根据get方法。获取每一个键对应的值。


2,Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了Set集合中。
而这个关系的数据类型就是:Map.Entry

练习(map_keySet and entrySet):

两种方法的用法:

class MapDemo2
{
	public static void main(String[] args) 
	{
		Map<String,String> map = new HashMap<String,String>();
		map.put("002","zhangsan2");
		map.put("003","zhangsan3");
		map.put("001","zhangsan1");
		map.put("004","zhangsan4");
	
		public static void mehod_1(HashMap<String,String> map)
		{
			//将map集合中的映射关系取出,存入到Set集合中,
			Set<Map.Entry<String,String>> entrySet = map.entrySet();	
			Iterator<Map.Entry<String,String>> it = entrySet.iterator();
			while(it.hasNext())
			{
				Map.Entry<String,String> me = it.next();
				String key = me.getKey();
				String value = me.getValue();
				System.out.println(key+":"+value);
			}
		}
		public static void method_2(HashMap<String,String> map)
		{
			//先获取map集合中的所有键的Set集合,keyset();
			Set<String> keySet = map.keySet();
			//有了Set集合就可以获取其迭代器了。
			Iterator<String> it = keySet.iterator();
			while(it.hasNext())
			{
				String key = it.next();
				// 有了键就可以通过map集合的get方法获取其对应的值。
				String value = map.get(key);
				System.out.println("key:"+key+",valur:"+value);
			}
		}		
	}
}

练习(Map):

"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。

希望打印结果:a(1)c(2).......

 

import java.util.*;
class MapTest3
{
	public static void main(String[] args) 
	{
		String s = charCount("sdfgzxcvasdfxcvdf");
		System.out.println(s);	
	}
	public static String charCount(String str)
	{
		char[] chs = str.toCharArray();

		TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
		
		int count = 0;

		for(int x=0; x<chs.length; x++)
		{

			if(!(chs[x]>='a'&& chs[x]<='z'|| chs[x]>='A'&& chs[x]<='Z'))
				continue;

			Integer value = tm.get(chs[x]);//返回值
			if(value!=null)
				count = value;
			count++;
			tm.put(chs[x],count);
			count = 0;

		StringBuilder sb = new StringBuilder();
		Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet();
		Iterator<Map.Entry<Character,Integer>> it = entrySet.iterator();
		while(it.hasNext())
		{
			Map.Entry<Character,Integer> me = it.next();
			Character ch = me.getKey();
			Integer value = me.getValue();
			sb.append(ch+"("+value+")");
		}
		return sb.toString();
	}
}


 


 

posted on 2014-11-15 14:53  grkbeyonf  阅读(140)  评论(0编辑  收藏  举报

导航