黑马程序员-java基础-集合

-------------------------ASP.Net+Unity开发、.Net培训、期待与您交流!--------------------------

集合

1、集合的特点
第一,集合是用来存储对象的,而且存储的是对象的地址而不是对象本身。
第二,集合中可以存储任何类型的对象,并且集合的长度可变。
2、集合和数组的区别
集合可以存储任何类型的元素,而数组只能存储相同类型的元素;
集合的长度可变,而数组的长度是固定的。
3、集合的分类
List :元素是有序的,元素可以重复
LinkedList:底层的数据结构使用的是链表数据结构
ArrayList:底层的数据结构使用的是数组数据结构
Set :元素是无序的,元素不可以重复
HashSet :底层的数据结构使用的是哈希表
TreeSet :底层的数据结构使用的是二叉树
-----------------------------------------------------------------------------------
集合的共性方法
1
、添加元素:boolean add(Object obj)
2、删除元素:boolean remove(元素)
3、清空集合:void clear()
4、判断元素:boolean contain(元素)
判断集合是否为空:boolean isEmpty()
5、获取元素个数:int size()
6、取出元素利用迭代器:Interator it=集合.iterator();

例子:

/*
Collection 集合中的共性方法
*/
import java.util.*;
class  CollectionDemo
{
	public static void main(String[] args) 
	{
		/*
		1.//未使用泛型时的情况 由于并未固定集合中元素的类型   所以什么类型都行
		ArrayList al=new ArrayList();//定义一个容器
		al.add("java01");
		al.add("java02");
		al.add(4);
		Iterator it=al.iterator();
		while (it.hasNext())
		{
			sop(it.next());	
		}
		*/
		//2.使用泛型的情况 则集合中元素的类型就是固定的
		ArrayList<String> al=new ArrayList<String>();
		al.add("java01");//给集合添加元素  其实为Object obj ="java01";即多态  向上转型
		al.add("java02");
		al.remove("java03");//删除集合中的元素  
		//al.add(4);
		Iterator<String> it=al.iterator();//遍历集合中的元素
		while (it.hasNext())
		{
			String s=(String)it.next();//由于确定了是什么类型 所以可以向下转型 所以可以利用字符串的特有属性 方法。
			sop(s);
			sop("长度为:"+s.length());	
		}
		sop(al.size());
		sop(al.contains("java01"));
	}
	public static void sop(Object b)
	{
		System.out.println(b);
	}
}
------------------------------------------------------------------------------------
List集合
1、
包括:ArrayList LinkedList
2、List集合的共性方法:
在指定位置添加元素:void add(int index,元素)
删除指定位置的元素:元素类型 remove(int index)
修改指定位置的元素:元素类型 set(int index,newElement)
通过角标获取指定位置元素:元素类型 get(int index)
3.List集合的特有迭代器:ListIterator
ListIterator 是Iterator的子接口,在迭代的过程中,不可以通过集合对象的方法来操作
集合中的元素,会发生ConcurrentModificationException异常。所以在迭代时,只能用迭代器的方法
来操作元素,可是Iterator的方法是有限的,只能对元素进行判断,取出,删除的动作。如果想要其他的
操作,如添加、修改等,就需要使用其子接口ListIterator。
创建ListIterator对象:ListIterator li=al.listIterator();
例子:

/*
List集合中的共性方法
*/
import java.util.*;
class ListDemo 
{
	public static void main(String[] args) 
	{
		ArrayList al=new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add(1,"java hello");//List集合的特有方法 即通过角标对集合进行操作
		//通过通用方法对集合进行遍历
		Iterator it=al.iterator();
		while (it.hasNext())
		{
			sop(it.next());	
		}
		//sop(al);
		sop("-------------------------");
		//通过List集合的特有迭代器来对集合进行访问 此迭代器在迭代的过程中可以对集合进行别的操作
		ListIterator li=al.listIterator();
		while (li.hasNext())
		{
			Object obj=li.next();
			if (obj.equals("java02"))
			{
				//li.add("java003");//在迭代的过程中进行添加元素
				li.set("java002");//在迭代的过程中进行修改元素(这两个方法不可以同时进行操作 因为不知道该不该操作此元素)
			}
			sop(obj);//依然打印不出新添加的元素	
		}
		//sop(al);
		for (int x=0;x<al.size() ;x++ )
		{
			sop(al.get(x));//通过List的特有方法即通过角标对元素进行方法 遍历。
		}
	}
	public static void sop(Object b)
	{
		System.out.println(b);
	}
}
------------------------------------------------------------------------------------
LinkedList
1
、它的特有方法
添加元素:void addFirst(E e)//在集合的第一个位置添加元素
void addLast(E e) //在集合的最后一个位置添加元素
获取元素: E getFirst() //获取此集合的第一个元素
E getLast() //获取此集合的最后一个元素
删除元素: E removeFirst()//移除此集合的第一个元素,并返回此元素
E removeLast() //移除此集合的最后一个元素,并返回此元素
2、对于此集合而得到的思想
由于此集合具有在第一个位置和最后一个位置添加元素的特性以及移除第一个位置和移除
第二个位置元素的额特性。则可以通过此集合来模拟一个堆栈或者队列的数据结构
具体程序如下:

具体程序如下:
/**
需求:使用LinkedList模拟一个堆栈或者队列的数据结构。
思路:1.要想模拟堆栈或者队列的数据结构 首先应该知道他们的特点
		 堆栈:先进后出
		 队列:先进先出
	  2.根据他们的特点  然后再创建相应的方法--存入方法 和取出方法
	  3.使用LinkedList中的方法来实现堆栈和队列
步骤:
1,定义一个类来实现堆栈或者队列
2,定义此类中的成员变量和成员函数
3,成员函数即实现此堆栈或者队列的特点 即利用LinkedList中的特有方法来实现
*/
import java.util.*;
class DuiZhan
{
	private LinkedList ll;
	DuiZhan()
	{
		ll=new LinkedList();

	}
	//实现存放的功能
	public void set(Object obj)
	{
		ll.addFirst(obj);
	}
	//实现获取的功能
	public Object get()
	{
		return ll.removeFirst();
	}
	public int size()
	{
		return ll.size();
	}
  public boolean isNull()
	{
		return ll.isEmpty();
    }
}
class LinkedListDemo 
{
	public static void main(String[] args) 
	{
		DuiZhan dz=new DuiZhan();
		dz.set("java05");
		dz.set("java02");
		dz.set(3);
		int y=dz.size();
		for (int x=0; x<y;x++ )//此处不能直接写x<dz.size() 因为循环一次则调用一次dz.size()
		                       //所以长度会慢慢减小
		{
			sop(dz.get());
		}
	}
	public static void sop(Object b)
	{
		System.out.println(b);
	}
}
------------------------------------------------------------------------------------
Set集合中的方法和Collection的共性方法是一样的。下面具体介绍Set的两个子类的作用和方法
HashSet
1
、存储的元素是无序的,元素是无重复,并且存入的是自定义对象。
2、HashSet是如何保证元素的唯一性的呢?
是通过元素的两个方法:hashCode和equals来完成的。如果元素的hashCode值相同,才会判断
equals是否是true。如果元素的hashCode值不同,不会调用equals方法。所以对于自定义对象,要
存入HashSet集合中,为了保证元素的唯一性,必须复写HashCode方法和equals方法。
3、对于HashSet集合中判断元素是否存在以及删除元素,依赖的也是HashCode方法和equals方法
4、注意:hashCode方法本身比较的是对象的地址值。所以若不复写,则是去除不了重复元素的。

例子:需求:向HashSet集合中存入自定义Person对象
	import java.util.*;
	class HashSetTest 
	{
		public static void sop(Object b)
		{
			System.out.println(b);
		}
		public static void main(String[] args) 
		{
			HashSet hs=new HashSet();
			hs.add(new Person("a1",71));
			hs.add(new Person("a2",73));
			hs.add(new Person("a3",74));
			hs.add(new Person("a1",71));
			//遍历此集合
			Iterator it=hs.iterator();
			while (it.hasNext())
			{
				//向下转型,为了用Person类的特有方法
				Person p=(Person)it.next();
				sop(p.getName()+"::"+p.getAge());	
			}
		}
	}
	class Person
	{
		private String name;
		private int age;
		Person(String name,int age)
		{
			this.name=name;
			this.age=age;
		}
		//复写hashCode方法
		public int hashCode()
		{
			return name.hashCode()+age;
		}
		//复写equals方法
		public boolean equals(Object obj)
		{
			if (!(obj instanceof Person))
			{
				return false;
			}
			Person p=(Person)obj;
			return this.name.equals(p.name)&&this.age==p.age;
		}
		public String getName()
		{
			return name;
		}
		public int getAge()
		{
			return age;
		}
	}
----------------------------------------------------------------------------------
TreeSet
1
、TreeSet集合的底层数据结构为二叉树
2、此集合可以对Set集合中的元素进行排序(按字母的自然顺序,且大写的在小写的字母前面)
3、TreeSet集合对元素进行排序的原理
此元素需要实现Comparable接口并复写comparaTo方法,才能对元素进行排序
4、TreeSet集合存储自定义对象,对对象实现排序功能的方法有两种;
第一,元素自身具备比较性,即实现Comparable接口并复写comparaTo方法
第二,集合本身具备比较性,即在集合的构造函数里传入Comparator接口类型的对象。
即,定义一个类实现Comparator接口,并覆盖compara方法。并将此类对象作为参数传递给
TreeSet集合的构造函数中。
注意,当这两中排序方式同时都存在时,则集合本身具备比较性优先。
注意,在比较的时候,当主要条件相同时,则判断次要条件。

/*
需求:向集合TreeSet中存入自定义对象Student,并按年龄进行排序,将年龄和名字相同者视为同一个人。
*/
//元素自身具备比较性
class Student implements Comparable
{
	private int age;
	private String name;
	Student(int age,String name)
	{
		this.age=age;
		this.name=name;
	}
	//复写Comparable接口的方法Comparable
	public int comparaTo(Object obj)
	{
		if (!(obj instanceof Student))
		{
			throw new RuntimeException("不是学生对象");
		}
		Student s=(Student)obj;
		if (this.age>s.age)
			return 1;
		if (this.age=age)//当主要条件相等时,比较次要条件
			return this.name.comparaTo(p.name);
		return -1;
	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
}
//第二种方式排序,即用比较器,使集合自身具备比较性
class MyCompara implements Comparator
{
	public int compara(Object 01,Object 02)
	{
		Student s1=(Student)01;
		Student s2=(Student)02;
		//以姓名排序
		int num=s1.getName().comparaTo(s2.getName());
		if (num==0)
		{
			//当主要条件相同时,看次要条件。
			return new Integer(s1.getAge()).comparaTo(new Integer(s2.getAge()));
		}
		return num;
	}
}
class TreeSetTest 
{
	public static void main(String[] args) 
	{
		TreeSet ts=new TreeSet(new MyCompara());//让集合自身具备比较功能
		ts.add(new Student("lisi02",22));
		ts.add(new Student("lisi02",21));
		ts.add(new Student("lisi007",20));
		ts.add(new Student("lisi09",19));
		ts.add(new Student("lisi06",18));
		ts.add(new Student("lisi06",18));
		Iterator it = ts.iterator();
		//对集合进行遍历
		while(it.hasNext())
		{
			Student stu = (Student)it.next();
			System.out.println(stu.getName()+"..."+stu.getAge());
		}
	}
}
--------------------------------------------------------------------------------
Map 集合
1
、Map集合并不是Collection的一种,它是独立的接口
2、Map集合的特点
该集合存储键值对,一对一对往里存,而且保证键的唯一性。
3、Map的子类:
Hashtable:底层是哈希表数据结构,不可以存入null键和null值
用作键的对象必须实现hashCode方法和equals方法;该集合是
线程同步的。
HashMap:底层是哈希表数据结构,允许使用null值和null键,该集合是不同步的。效率较高
TreeMap:底层是二叉树数据结构,线程不同步。可以用于给Map集合中的键进行排序。
Map和Set很像,其实Set底层就是使用了Map集合。
4、Map集合的共性方法
添加元素: V put(K key, V value )
删除元素: V remove(Object key)
清空集合:void clear()
判断: boolean containsKey(Object key)
如果此映射包含指定键的映射关系,则返回 true。
boolean containsValue(Object value)
如果此映射将一个或多个键映射到指定值,则返回 true
boolean isEmpty()//判断集合是否是空的。
获取: V get(Object key) //获取键所对应的值
int size() //获取集合的大小
5、对于Map集合中元素的取出方式
第一,利用keySet:将map中的所有键存入set集合,因为set具备迭代器,所以可以通过迭代器
方式取出所有的键,再根据get方法,获取每一个键对应的值。
第二,entrySet:将map集合的映射关系直接存入到了set集合中,而这个关系数据类型就是Map.Entry
Entry其实就是Map中的一个static内部接口。
代码:

import java.util.*;
class MapDemo2 
{
	public static void main(String[] args) 
	{
		Map<String,String> map = new HashMap<String,String>();
		map.put("02","zhangsan2");
		map.put("03","zhangsan3");
		map.put("01","zhangsan1");
		map.put("04","zhangsan4");
		//第二种排序方式
		//将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);

		}
		/*第一种排序方式
		//先获取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+",value:"+value);
		}
		*/
	}
}
--------------------------------------------------------------------------
HashMap保证元素唯一性的原理和HashSet是一样的,所以不再赘述
TreeSet对元素的排序原理和TreeSet是一样的,同样不再赘述。
练习:对于HashMap集合的练习

/*
每一个学生都有对应的归属地。
学生Student,地址String。
学生属性:姓名,年龄。
注意:姓名和年龄相同的视为同一个学生。
保证学生的唯一性。
获取map集合中的元素。
*/

import java.util.*;
class Student 
{
	private String name;
	private int age;
	Student(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	//复写hashCode方法
	public int hashCode()
	{
		return name.hashCode()+age*34;
	}
	//复写equals方法
	public boolean equals(Object obj)
	{
		if(!(obj instanceof Student))
			throw new ClassCastException("类型不匹配");

		Student s = (Student)obj;

		return this.name.equals(s.name) && this.age==s.age;
	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
	public String toString()
	{
		return name+":"+age;
	}
}
class  MapTest
{
	public static void main(String[] args) 
	{
		HashMap<Student,String> hm = new HashMap<Student,String>();

		hm.put(new Student("lisi1",21),"beijing");
		hm.put(new Student("lisi1",21),"tianjin");
		hm.put(new Student("lisi2",22),"shanghai");
		hm.put(new Student("lisi3",23),"nanjing");
		hm.put(new Student("lisi4",24),"wuhan");
		//利用 keySet取出元素
		Set<Student> keySet = hm.keySet();
		Iterator<Student> it = keySet.iterator();
		while(it.hasNext())
		{
			Student stu = it.next();
			String addr = hm.get(stu);
			System.out.println(stu+".."+addr);
		}
	}
}
练习:对TreeSet集合的练习
/*
练习:
"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。
希望打印结果:a(1)c(2).....

通过结果发现,每一个字母都有对应的次数。
说明字母和次数之间都有映射关系。所以选择map

思路:
1,将字符串转换成字符数组。因为要对每一个字母进行操作。
2,定义一个map集合,因为打印结果的字母有顺序,所以使用treemap集合。
3,遍历字符数组。
	将每一个字母作为键去查map集合。
	如果返回null,将该字母和1存入到map集合中。
	如果返回不是null,说明该字母在map集合已经存在并有对应次数。
	那么就获取该次数并进行自增。,然后将该字母和自增后的次数存入到map集合中。覆盖调用原理键所对应的值。
4,将map集合中的数据变成指定的字符串形式返回。
*/
import java.util.*;
class  MapTest3
{
	public static void main(String[] args) 
	{
		String s= charCount("ak+abAf1c,dCkaAbc-defa");
		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();
		//取出集合中的元素,并存入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();
	}
}


-------------------------ASP.Net+Unity开发、.Net培训、期待与您交流!--------------------------


详情请查看:http://edu.csdn.net





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章