黑马程序员——集合框架类学习

------- android培训java培训、期待与您交流! ----------

一、Collection接口,该接口提供了一些对集合类对象的基本操作方法,下面有两个主要的子类——List和Set集合类。List和Set的相同点是都实现了Collection接口,都有一些共性的基本操作方法。区别是List集合类保存的元素是有序的(即存的顺序和取出的顺序一致),元素是可以重复的,而且带有索引。Set集合类则是无序的、元素不可重复,没有索引。

1、List类的常用子类——ArrayList、LinkedList和Vector,由于ArrayList最常用,故以ArrayList说明问题,为了在编程过程中保存类型安全,需要在使用集合类的时候指定接收类型(即泛型问题)。ArrayList底层是通过数组来实现的,故它存在索引访问方式,同时还可以通过通用的迭代器来遍历集合类的元素。它的特点是:通过索引访问元素效率比较高,然而,在增加和删除元素时,由于处理位置后面的元素需要进行移位操作,索引使得在增删操作时效率不高。eg:

class ArrayTest
{
public static void main(String[] args)
{
ArrayList<String> arrList=new ArrayList<String>();//注意在指定接收类型的时候,要用引用对象类型,不能使用基本数据类型,例如要存int类型元素,指定类型就为其封装类Integer
arrList.add("tianjin");//添加元素
arrList.add("shanghai");
arrList.add("beijing");
arrList.add(1,"wuhan");//在指定位置添加元素
arrList.set(2,"hangzhou");//修改指定位置的元素信息

//集合类的遍历,第一种通过索引
for(int i=0;i<arrList.size();i++)
{
System.out.println("遍历元素"+i+":"+arrList.get(i));
}
//第二种遍历方式,通过Iterator迭代器实现
int index=0;
Iterator<String> iter=arrList.iterator();//调用iterator方法返回一个迭代器
while(iter.hasNext())//通过Iterator的hasNext方法判断元素是否存在
{
System.out.println("遍历元素"+index+":"+iter.next());
index++;
}
}
}


当然,也可以保存自定义的复杂结构的数据,整个操作过程大致是一样的。注意:在使用Iterator迭代器遍历元素过程中对元素进行添加、删除等操作是不可以的,会报ConcurrentModificationException异常,这是由于你在删除元素的时候,集合类和迭代器同时操作元素,在迭代器中进行引用元素的删除操作,迭代器自身并不知道,故产生了该异常。

问题解决:可以通过Iterator下的一个子类对象ListIterator来操作,因为在该类下有一些对元素进行增删改查操作的基本方法,而通过List的listIterator方法正好可以返回一个ListIterator对象,进而可以对集合类元素进行操作。

二、Set集合类的应用:有两个常用集合HashSet和TreeSet。由其名字就可以知道HashSet底层是通过哈希表来实现的,故是无序保存且是保证元素唯一的;而TreeSet底层是通过二叉树数据结构来实现的,可以对其内部元素进行自然排序,不可有重复元素。

1、首先,HashSet是通过哈希表来保存元素的,哈希表中是按照哈希值进行排序,而要保证元素的唯一性就是通过元素的hashCode和equals方法共同完成的。保证元素唯一的原理是:对存进来的元素首先判断其hashCode的返回值是否相同,如果不同说明元素唯一,则存入集合中;如果哈希值相同则会通过调用元素自身的equals方法来判断元素值是否相同(通过equals的返回值,0表示元素值相同),相同则不予存储。

所以,要想往Set集合类中存入自定义对象元素,在创建自定义对象的时候就要复写hashCode和equals方法,保证对象能够正确地存入HashSet中。

import java.util.*;
class HashSetDemo 
{
	public static void main(String[] args) 
	{
		/*HashSet<String> hSet=new HashSet<String>();
		hSet.add("beijing");
		hSet.add("tianjin");
		hSet.add("hangzhou");
		hSet.add("shanghai");
		hSet.add("shengzhen");
		//添加两个重复的元素
		hSet.add("beijing");
		hSet.add("tianjin");

		System.out.println(hSet);//打印数据可以看出元素是无序的,但是,
		//beijing和tianjing两个重复的元素没有保存下来,说明,Set集合保证了元素唯一
		//其原理:主要是调用了String类中的hashCode和equals方法,所以在创建自定义类的时候,
		//有必要对这两个方法进行复写,否则在存入Set集合时无法保证元素唯一*/

		//创建一个用于保存Person元素的Set集合类对象
		HashSet<Person> hash=new HashSet<Person>();
		hash.add(new Person("gao1","1234"));
		hash.add(new Person("guo","1354"));
		hash.add(new Person("zhang","1432"));
		hash.add(new Person("wang","1634"));
		hash.add(new Person("gao1","1623"));
		hash.add(new Person("gao","1234"));

		//System.out.println(hash);
		//输出元素数据
		Iterator<Person> iter=hash.iterator();
		while(iter.hasNext())
		{
			Person p=iter.next();
			System.out.println("PersonName:"+p.getName()+"   "+"PersonId:"+p.getId());
		}
		//
	}
}
//创建一个Person类,有姓名和身份证号两个属性,
//靠身份证号来确定Person对象的唯一性
class Person
{
	private String name;//姓名
	private String id;//身份证号
	public Person(String name,String id)
	{
		this.name=name;
		this.id=id;
	}
	public void setName(String name)
	{
		this.name=name;
	}
	public void setId(String id)
	{
		this.id=id;
	}
	public String getName()
	{
		return name;
	}
	public String getId()
	{
		return id;
	}
	//注意为了让该类的对象能够作为元素存入到Set集合类中,需要复写两个方法
	public int hashCode()
	{
		return this.id.hashCode();//身份证号唯一确定哈希码(不能用重复的身份证号)
	}
	public boolean equals(Object obj)
	{
		if(!(obj instanceof Person))
			throw new RuntimeException("比较类型不匹配!");
		Person p=(Person)obj;
		return this.id.equals(p.getId());
	}
}

输出结果:

在使用该集合类的时候最重要的一点就是,要根据该集合类保证成员唯一性的特点,在你存储数据的类型中要根据需求复写hashCode和equals方法。

2、Set集合类中的另一个常用的子类是TreeSet,该类的底层是通过二叉树结构来实现的,即有个参考根节点,然后比根节点大的存到右子树,小的存到左子树。所以,该集合类的特点就是可以对里面的元素排序,排序的原理是通过一个比较器或者实现接口Comparable中的comapreTo方法实现(根据其返回值-正数、负数、0(表示重复元素不予保存))。

实现比较的两种方式:1、通过复写接口Comparable的compareTo方法,实现自定义排序。2、通过自行设计一个继承自Coparator的子类,复写compare(s1,s2)的方法,然后在应用时创建一个比较器(自己设计的类)引用对象,然后将其作为参数传递给TreeSet的构造函数即可。

<pre name="code" class="java">import java.util.*;
class HashSetDemo1 
{
	public static void main(String[] args) 
	{
		/*HashSet<Person> hash=new HashSet<Person>();
		hash.add(new Person("gao1","1234"));
		hash.add(new Person("guo","1354"));
		hash.add(new Person("zhang","1432"));
		hash.add(new Person("wang","1634"));
		hash.add(new Person("gao1","1623"));
		hash.add(new Person("gao","1234"));

		Iterator<Person> iter=hash.iterator();
		while(iter.hasNext())
		{
			Person p=iter.next();
			System.out.println("PersonName:"+p.getName()+"   "+"PersonId:"+p.getId());
		}*/


		//利用TreeSet集合类保存Person对象元素
		TreeSet<Person> tree=new TreeSet<Person>(new NewComparator());//第二种方式——传入一个自定义比较器的引用,该方式具有较高优先级
		tree.add(new Person("gao1","1234"));
		tree.add(new Person("guo","1354"));
		tree.add(new Person("zhang","1432"));
		tree.add(new Person("wang","1634"));
		tree.add(new Person("gao1","1623"));
		tree.add(new Person("gao","1234"));
		//System.out.println(hash);
		//输出元素数据
		Iterator<Person> iter=tree.iterator();
		while(iter.hasNext())
		{
			Person p=iter.next();
			System.out.println("PersonName:"+p.getName()+"   "+"PersonId:"+p.getId());
		}
		//
	}
}
//创建一个Person类,有姓名和身份证号两个属性,
//靠身份证号来确定Person对象的唯一性
class Person implements Comparable<Person>
{
	private String name;//姓名
	private String id;//身份证号
	public Person(String name,String id)
	{
		this.name=name;
		this.id=id;
	}
	public void setName(String name)
	{
		this.name=name;
	}
	public void setId(String id)
	{
		this.id=id;
	}
	public String getName()
	{
		return name;
	}
	public String getId()
	{
		return id;
	}
	//注意为了让该类的对象能够作为元素存入到Set集合类中,需要复写两个方法
	public int hashCode()
	{
		return this.id.hashCode();//身份证号唯一确定哈希码(不能用重复的身份证号)
	}
	public boolean equals(Object obj)
	{
		if(!(obj instanceof Person))
			throw new RuntimeException("比较类型不匹配!");
		Person p=(Person)obj;
		return this.id.equals(p.getId());
	}
	//为适应TreeSet集合类的存储,需要实现接口Comparable,复写compareTo方法——第一种控制排序的方式
	public int compareTo(Person p)
	{
		//按姓名排序
		int num=this.name.compareTo(p.getName());
		if(0==num)
			return this.id.compareTo(p.getId());
		return num;
	}
}

//第二种控制比较排序的方式,创建Comparator的子类
class NewComparator implements Comparator<Person>
{
	public int compare(Person p1,Person p2)
	{
		//按照身份证号的顺序排序
		return p1.getId().compareTo(p2.getId());
	}
}


 运行结果: 
 
 

三、Map集合类:Map和Collection的最大的不同就是:Collection是单列存储元素——即元素值,而Map存储双列元素——实际保存的是<Key,Value>的键值对组合。常用的两个子类是HashMap和TreeMap,他们的底层实现结构同HashSet和TreeSet一样,分别是哈希表和二叉树。该集合类也提供了对集合进行操作的基本方法如添加put(k,v),删除remove(k),判断cotainsKey(k)、containsValue(v)、isEmpty(),获取get(k)。

注意:Map集合类无法直接遍历自身的元素,而是要通过返回Set集合对象的方式,然后通过Set结合的迭代器方式去遍历Map自身的元素信息。这里有两个重要方法:Set<Key> keySet()和Set<Map.Entry<Key,Value>> entrySet(),他们返回的都是一个Set集合对象,但是这两个集合对象里的元素是不同的:第一个保存的是Key,而第二个保存的是Key和Value的映射关系——Map.Entry<Key,Value>。具体操作见实例:

import java.util.*;

//将Person类的对象与其对于的电话号码作为一组键值对,保存到TreeMap中,其中Person对象为Key,电话号码为Value
class TreeMapDemo 
{
	public static void main(String[] args) 
	{

		//利用TreeMap集合类保存Person对象和电话号码键值对元素
		TreeMap<Person,String> tree=new TreeMap<Person,String>();
		tree.put(new Person("gao1","1234"),"13523452");
		tree.put(new Person("guo","1354"),"132243452");
		tree.put(new Person("zhang","1432"),"138267842");
		tree.put(new Person("wang","1634"),"18723494");
		tree.put(new Person("gao1","1623"),"15224252");
		tree.put(new Person("gao","1234"),"1513523452");
		//System.out.println(hash);
		//通过keySet方法返回保存Key的Set集合,通过操作Set集合的Iterator对象来遍历Map中的元素
		System.out.println("第一种遍历方式的结果:");
		Set<Person> set=tree.keySet();
		Iterator<Person> iter=set.iterator();
		while(iter.hasNext())
		{
			Person p=iter.next();
			System.out.println("PersonName:"+p.getName()+"   "+"PersonId:"+p.getId()+"--电话号码:"+tree.get(p));
		}
		//通过entrySet方式遍历
		System.out.println("第二种遍历方式的结果:");
		Set<Map.Entry<Person,String>> entrySet=tree.entrySet();
		Iterator<Map.Entry<Person,String>> entryIter=entrySet.iterator();
		while(entryIter.hasNext())
		{
			Map.Entry<Person,String> entry=entryIter.next();
			Person p=entry.getKey();
			System.out.println("PersonName:"+p.getName()+"   "+"PersonId:"+p.getId()+"--电话号码:"+entry.getValue());
		}
	}
}
//创建一个Person类,有姓名和身份证号两个属性,
//靠身份证号来确定Person对象的唯一性
class Person implements Comparable<Person>
{
	private String name;//姓名
	private String id;//身份证号
	public Person(String name,String id)
	{
		this.name=name;
		this.id=id;
	}
	public void setName(String name)
	{
		this.name=name;
	}
	public void setId(String id)
	{
		this.id=id;
	}
	public String getName()
	{
		return name;
	}
	public String getId()
	{
		return id;
	}
	//注意为了让该类的对象能够作为元素存入到Set集合类中,需要复写两个方法
	public int hashCode()
	{
		return this.id.hashCode();//身份证号唯一确定哈希码(不能用重复的身份证号)
	}
	public boolean equals(Object obj)
	{
		if(!(obj instanceof Person))
			throw new RuntimeException("比较类型不匹配!");
		Person p=(Person)obj;
		return this.id.equals(p.getId());
	}
	//为适应TreeSet集合类的存储,需要实现接口Comparable,复写compareTo方法——第一种控制排序的方式
	public int compareTo(Person p)
	{
		//按姓名排序
		int num=this.name.compareTo(p.getName());
		if(0==num)
			return this.id.compareTo(p.getId());
		return num;
	}
}

//第二种控制比较排序的方式,创建Comparator的子类
class NewComparator implements Comparator<Person>
{
	public int compare(Person p1,Person p2)
	{
		//按照身份证号的顺序排序
		return p1.getId().compareTo(p2.getId());
	}
}

运作结果:


总结:对于哈希表结构实现的集合类,在自定义元素类型的时候,切记要根据需求复写两个方法——hashCode和equals;对于二叉树结构实现的集合类,在自定义元素类型是要实现接口Comparable的compareTo方法或者自定义比较器实现接口Comparator,复写compare方法,然后将其引用作为参数传递给Tree集合类的构造函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
黑马程序员的tb_brand是指在JavaWeb基础教程中创建的一个表。这个表是用来存储品牌信息的,具体的表结构和数据型需要和JavaBean中的成员变量保持一致。\[1\]在这个教程中,使用了Maven来构建项目,并且使用了MyBatis作为持久层框架,通过配置pom.xml文件来引入相关依赖。\[2\] Maven是一个用于管理和构建Java项目的工具,它提供了一套标准化的项目结构、构建流程和依赖管理机制。\[3\] #### 引用[.reference_title] - *1* [【JAVAWEB开发】黑马程序员java web案例资料(含Element的删除与修改)](https://blog.csdn.net/aasd23/article/details/126940147)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [黑马程序员-MyBatis 框架-最全入门笔记、阿伟看了都得说真大、真细、真全!!!](https://blog.csdn.net/qq_57383364/article/details/128103058)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [JavaWeb——黑马程序员课程笔记](https://blog.csdn.net/King_ZACC/article/details/128573804)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值