常用集合的总结及遇到的问题

本文深入浅出地介绍了Java集合框架中的ArrayList、HashMap、HashSet和TreeSet四种常用集合的特点及其应用场景,详细阐述了每种集合的定义、添加、遍历和输出方法,并探讨了集合的输出机制,最后附带了夯实基础的练习题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

依稀记得去年三月中旬第一次真正接触集合,当时觉得天崩地裂,怎么学都是蒙的,由此,当时记录了很多笔记,在此做一个积累,便于日后添加和查阅。

1、常用的四个集合ArrayList、HashMap、HashSet和TreeSet及区别

/*
 * ArrayList、HashMap、HashSet、TreeSet这四个集合的一系列运用和规律
 */
public class ExampleGather {

	/*
	 * 泛型:泛型只在编译阶段有效,在运行阶段会去泛型化;
	 *      也就是说泛型只在逻辑上看不同,实际用途相同。
	 * 
	 * 总结:
	 * ArrayList、HashMap、HashSet、TreeSet四个集合中
	 * 1.HashMap不能直接遍历,需要通过Set objSet = objHashMap.Keyset();之后才能遍历
	 * 2.TreeSet需要自定义比较方法才能输出,否则报错,
	 *   其中自定义的比较方法需要调用系统的串口Comparator
	 * 3.在输出的时候需要看每个集合中内容的类型,如果是八大基本数据类型的包
	 *   装类,可以直接输出(具体请看第二部分);如果是自定义的类充当类型
	 *   (例如Student),需要如下书写规范objStudent.intNo,也就是需要
	 *   写出自定义类中,具体输出什么内容
	 */

	// ArrayList可以输出重复元素,怎么放入,怎么输出
	// HashMap不可以输出重复元素,无论怎么放入,按照逻辑顺序输出
	// HashSet不可以输出重复元素,无论怎样放入,按照哈希算法输出
	// TreeSet不可以输出重复元素,无论怎样放入,按照我们定义的比较方法输出

	// **********如果有重复元素,后面替代前面,之后按照相应集合方式输出*******************
	public void getSummary() {
		/*
		 * 集合ArrayList的定义,添加,遍历,输出
		 */
		/*
		 * 八大基本数据类型存储在栈中;String既可存储在堆中,也可存储在栈中。
		 * eg:String str = "abc"             栈中 
		 *    String str = new String("abc") 堆中
		 */
		List<String> objArrayList = new ArrayList<String>(); //这样定义也可以,后面的new才是实例化对象
		objArrayList.add("a");
		objArrayList.add("b");
		objArrayList.add("a");
		objArrayList.add(1, "c");
		objArrayList.remove(2);
		System.out.println("输出ArrayList1: " + " " + objArrayList); //这里数据存储在栈中,所以输出是数据
		//输出ArrayList1:  [a, c, a]
		objArrayList.remove("a"); //按顺序先删除第一个a
		objArrayList.set(0, "z");
		// 一共有三种遍历方式,一二不需要迭代器,但是迭代器更好用
		// 一
		for (int i = 0; i < objArrayList.size(); i++) { //for()循环以数组形式输出
			System.out.println("输出ArrayList2: " + " " + objArrayList.get(i));
			//输出ArrayList2:  z
			//输出ArrayList2:  a
		}

		// 二
		for (String str : objArrayList) { //for-each()循环以数组形式输出
			System.out.println("输出ArrayList3: " + " " + str); //这个循环没有下标,所以不能增删,但是速度快
			//输出ArrayList3:  z
			//输出ArrayList3:  a
		}

		// 三
		Iterator<String> it = objArrayList.iterator(); //遍历循环输出,和for-each()循环效果一样
		while (it.hasNext()) {
			String str = it.next();
			System.out.println("输出ArrayList4: " + " " + str);
			//输出ArrayList3:  z
			//输出ArrayList3:  a
		}

		/*
		 * 集合HashMap的定义,添加,遍历,输出,其中在遍历之前有两种
		 * 方法可以实现遍历,一个keySet()方法,一个entrySet()方法
		 */
		/*
		 * 在集合中,如果类型是包装类和String,则集合可以直接输出,
		 * 不需要遍历也不需要for,这时输出的是数据
		 */
		HashMap<Integer, String> objMap = new HashMap<Integer, String>();
		objMap.put(1, "ly1");
		objMap.put(2, "ly2");
		objMap.put(1, "ly3");
		objMap.put(3, "ly2");
		System.out.println("输出ArrayList5: " + " " + objMap);
		//输出ArrayList5:  {1=ly3, 2=ly2, 3=ly2}
		/*
		 * 利用keySet()方法实现遍历
		 */
		Set<Integer> objSet = objMap.keySet();
		Iterator<Integer> it1 = objSet.iterator();

		while (it1.hasNext()) {
			int intKey = it1.next();
			System.out.println("输出HashMapKeySet1: " + " " + intKey + " " + objMap.get(intKey));
			//输出HashMapKeySet1:  1 ly3
			//输出HashMapKeySet1:  2 ly2
			//输出HashMapKeySet1:  3 ly2
		}

		/*
		 * 利用entrySet()方法实现遍历
		 */
		Set<Entry<Integer, String>> objSet1 = objMap.entrySet();
		Iterator<Entry<Integer, String>> it2 = objSet1.iterator();

		while (it2.hasNext()) {
			Entry<Integer, String> objEntry = it2.next();
			System.out.println("输出HashMapEntrySet2: " + " " + objEntry.getKey() + " " + objEntry.getValue());
			//输出HashMapEntrySet2:  1 ly3
			//输出HashMapEntrySet2:  2 ly2
			//输出HashMapEntrySet2:  3 ly2
		}

		/*
		 * 集合HashSet的定义,添加,遍历,输出
		 */
		HashSet<String> objHashSet = new HashSet<String>();
		objHashSet.add("ab");
		objHashSet.add("aas");
		objHashSet.add("fc");
		objHashSet.add("bc");
		Iterator<String> it3 = objHashSet.iterator();

		while (it3.hasNext()) {
			String str = it3.next();
			System.out.println("输出HashSet: " + " " + str);
			//输出HashSet:  ab
			//输出HashSet:  bc
			//输出HashSet:  aas
			//输出HashSet:  fc
		}

		/*
		 * 集合TreeSet的定义,添加,遍历,输出
		 */
		TreeSet<Student> objTreeSet = new TreeSet<Student>(new MyCompare());
		objTreeSet.add(new Student(3, "la3"));
		objTreeSet.add(new Student(3, "ly1"));
		objTreeSet.add(new Student(2, "ly2"));
		Iterator<Student> it4 = objTreeSet.iterator();

		while (it4.hasNext()) {
			Student objStudent = it4.next();
			System.out.println("输出TreeSet: " + " " + objStudent.intNo + " " + objStudent.strName);
			//输出TreeSet:  2 ly2
			//输出TreeSet:  3 la3
			//输出TreeSet:  3 ly1
		}

	}

	public static void main(String[] args) {
		ExampleGather objSum = new ExampleGather();
		objSum.getSummary();
	}
}

class Student {
	public int intNo;
	public String strName;

	public Student(int no, String name) {
		intNo = no;
		strName = name;
	}
}

class MyCompare implements Comparator<Object> {

	@Override
	public int compare(Object arg0, Object arg1) {

		Student objStu1 = (Student) arg0;
		Student objStu2 = (Student) arg1;
		int intResult;

		// if判断语句的简便写法,其中有三个判断
		intResult = objStu1.intNo > objStu2.intNo ? 1 : objStu1.intNo < objStu2.intNo ? -1 : 0;

		// 系统自带的比较方法compareTo
		if (intResult == 0) {
			intResult = objStu1.strName.compareTo(objStu2.strName);
		}

		return intResult;
	}

}

有关这四个集合的简单运用,代码中的注解已经标注的很清楚了,在这四个集合中,工作常用的是ArrayList和HashMap,这两者的区别尤为重要。

2、集合的输出机制

上面介绍集合的三种输出方式,for、foreach、迭代器,但在项目中最常用的是get()方法直接输出,接下来展示一段代码。

/**
 * 直接输出集合的解释:
 * 1.在aList集合中存储的数据类型是Point,则输出是地址,但是由于Point类中重写了toString()方法,所以输出是数据;
 * 2.而如果在aList集合中存储的数据类型是八大基本数据类型的包装类或String,则输出是数据,这是因为包装类中和String中都已经重写了toString了
 * 
 * 直接输出集合的原理:
 * 1.在输出集合全部数据的时候一共调用两个toString(),第一个是为了把数据用[]包起来,第二个是调用重写的toString())
 * 2.不过如果输出的是集合中第二条数据的intNumber变量的值无论是否重写toString()方法,都会输出数据,
 *   这是因为intNumber变量存储在栈中,而new Point(2,2)是存储在堆中,所以前者输出是数据,后者输出是地址
 */
List<Point> aList = new ArrayList<Point>();
aList.add(new Point(1,1));
aList.add(new Point(2,2));    
aList.add(new Point(3,3));
System.out.println("输出集合中全部数据:"+aList); //输出集合中全部数据:[1=1, 2=2, 3=3]
System.out.println("输出集合中第二条数据: "+aList.get(1)); //输出集合中第二条数据: 2=2
System.out.println("输出集合中第二条数据的intNumber变量的值: "+aList.get(1).intNumber); //输出集合中第二条数据的intNumber变量的值: 2

//以下是Point类
public class Point {
	public int intNumber;
	public int intNumber1;

	public Point(int intA, int intB) {
		this.intNumber = intA;
		this.intNumber1 = intB;
	}

	// 这个方法很重要,改变了全局内容
	// 因为Object中的toString()方法输出的是地址,这里重写了toString(),影响了println()返回的值,因此改变了全局
	public String toString() {
		return intNumber + "=" + intNumber1;
	}
}

这一部分当时纠结了好久,一直不是很懂,直到多次整理笔记之后才渐渐明了,后来又做过几个项目,随着对后端了解的加深,慢慢自然就懂了。

如果看了上面的原理还不懂,请参考如下有关System.out.println()的笔记来理解

public class ExampleToString1118 {
	/*
	 * 在Java中,所有的对象都是继承自Object,自然继承了toString方法,在当使用System.out.println()
	 * 里面为一个对象的引用时,自动调用toString方法将对象打印出来。 如果重写了tostring方法则调用重写的toString 方法。
	 * 
	 * 因为System.out.println()的这个方法源码中调用了String.valueOf(Objec o),源码如下:
	 * public void println(Object x) { 
	 * 		String s = String.valueOf(x);
	 * 		synchronized (this) { 
	 * 			print(s); newLine(); 
	 * 		} 
	 * }
	 * 
	 * 而String.valueOf(x)的源码就是去调用该对象的toString()方法,源码如下:
	 * public static String valueOf(Object obj) { 
	 * 		return (obj == null)?"null":obj.toString();
	 * }
	 */
	public static void main(String[] args) {
		System.out.println(new A());
		//输出我是A
		//输出com.examplegather.example.A@15db9742
	}
}

class A {
	public A() {
		System.out.println("我是A");
	}
}

3、集合夯实基础练习

当时我还做过两个练习题,练习题目如下:

HashMap<HashSet<Integer>, TreeSet<Student>> objHashMap = new HashMap<HashSet<Integer>, TreeSet<Student>>();

具体就是集合嵌套集合的如何输出?要求用迭代器输出,一个要求用HashMap中的keySet()方法输出,另一个要求用HashMap中的entrySet()方法输出,这两道题比较练习基本逻辑。

题目答案的代码文档在此链接中,有兴趣的可以下载
https://download.youkuaiyun.com/download/zcy92949/10363692

4、总结

以上就是我对集合中一些基本的理解,如有不对之处,希望诸君不吝赐教。

版权声明:本文出自孤星卟哭的博客,原创文章,转载请注明出处。 https://blog.youkuaiyun.com/zcy92949/article/details/80074839

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值