JAVA进阶 —— 集合进阶

目录

一、 双列集合

二、 Map

1. Map的常见API

2. Map的遍历方式

2.1 第一种遍历方式:键找值

2.2 第二种遍历方式:键值对

2.3 第三种遍历方式:Lambda表达式

三、 Map的三种实现类

1.  HashMap

 2.  LinkedHashMap

3. TreeMap

3.1 练习: TreeMap基本应用

3.2 练习:统计个数

四、 可变参数

五、Collections


一、 双列集合

我们通过单列集合和双列集合的对比进行学习:

  • 单列集合:每次只能添加一个元素
  • 双列集合:每次可以添加一对元素

双列集合特点:

  1. 双列集合一次需要存入一对数据,分别为
  2. 不能重复可以重复
  3. 键和值是一 一对应的,每一个键只能找到自己对应的值。
  4. 键 + 值这个整体 我们称之为“键值对” 或者 “键值对对象”,在Java中叫做Entry对象“”。

二、 Map

Map是双列集合的顶层接口,它的功能是全部双列集合都可以继承使用的。

1. Map的常见API

方法名称说明
 V put(K key,V value)添加 / 覆盖元素
V remove(Object key)根据键删除键值对元素
void clear()移除所有的键值对元素
boolean containsKey(Object key)判断集合是否包含指定的键
boolean containsvalue(Object value)判断集合是否包含指定的值
boolean isEmpty()判断集合是否为空
int size()集合的长度,也就是集合中键值对的个数
public class MapTest {
	public static void main(String[] args) {
		// 1.创建map集合对象
		Map<String, String> m = new HashMap<>();

		// 2.添加元素

		// 在添加数据时,如果键不存在,则直接将键值对对象添加到map集合中
		// 如果键存在,则会将原有键值对对象覆盖,并且被覆盖的值会进行返回

		String value1 = m.put("郭靖", "黄蓉"); // null
		System.out.println(value1);
		m.put("韦小宝", "沐剑屏");
		m.put("尹志平", "小龙女");

		String value2 = m.put("韦小宝", "双儿");
		System.out.println(value2); // 沐剑屏

		// 打印集合
		System.out.println(m); // {韦小宝=双儿, 尹志平=小龙女, 郭靖=黄蓉}

		// 3.删除元素
		String result = m.remove("郭靖");
		System.out.println(result); // 黄蓉

		// 4.判断是否包含
		boolean keyResult = m.containsKey("郭靖");
		System.out.println(keyResult); // false
		boolean valueResult = m.containsValue("小龙女");
		System.out.println(valueResult); // true

		// 5.判断集合是否为空
		boolean result1 = m.isEmpty();
		System.out.println(result1); // false

		// 7.求集合长度
		int size = m.size();
		System.out.println(size); // 2

		// 8.清空
		m.clear(); // 没有返回值
	}
}

2. Map的遍历方式

  1. 键找值
  2. 键值对
  3. Lambda表达式

2.1 第一种遍历方式:键找值

  • 通过keySet()方法将所有的键都放在一个单列集合当中。
  • 遍历单列集合依次得到每一个键。
  • 再通过get方法获取每一个键所对应的值。
public class MapTest {
	public static void main(String[] args) {
		// 1.创建map集合对象
		Map<String, String> m = new HashMap<>();

		// 2.添加元素
		m.put("郭靖", "穆念慈");
		m.put("欧阳克", "黄蓉");
		m.put("尹志平", "小龙女");

		//3.通过键找值
		
		//3.1 获取所有的键:把这些键放到一个单列集合当中
		Set<String> keys = m.keySet();
		//3.2 遍历单列集合得到所有的键
		for (String key : keys) {
			//3.3 通过map集合当中键获取值 get
			String value = m.get(key);
			System.out.println(key + " = " + value);
		}
	}
}

2.2 第二种遍历方式:键值对

  • 通过entrySet()方法依次获取每一个键值对对象
  • 再通过getKey() getValue()方法分别获取键和值
public class MapTest {
	public static void main(String[] args) {
		// 1.创建map集合对象
		Map<String, String> m = new HashMap<>();

		// 2.添加元素
		// 键: 人物外号
		// 值: 人物姓名
		m.put("标枪选手", "马超");
		m.put("人物挂件", "明世隐");
		m.put("御龙骑士", "花木兰");

		// 3.键值对
		// 3.1 获取所有的键值对对象 ,返回一个Set对象
		Set<Entry<String, String>> entries = m.entrySet();
		for (Entry<String, String> entry : entries) {
			// 3.2 遍历集合,获取每一个键值对对象
			String key = entry.getKey();
			String value = entry.getValue();
			System.out.println(key + " = " + value);
		}
	}
}

2.3 第三种遍历方式:Lambda表达式

方法名称说明
default void forEach(BiConsumer<? super K , ? super V> action)结合lambda遍历Map集合
public class MapTest {
	public static void main(String[] args) {
		// 1.创建map集合对象
		Map<String, String> m = new HashMap<>();

		// 2.添加元素
		//键: 人物名字
		//值: 名人名言
		m.put("鲁迅", "这句话是我说的");
		m.put("曹操", "不可能绝对不可能");
		m.put("刘备", "接着奏乐接着舞");
		m.put("柯镇恶", "看我眼色行事");

		// 3.lambda表达式
		
		//forEach底层:
		//利用第二种遍历方式进行遍历,依次得到每一个键和值
		//再利用accept方法
		
		m.forEach(new BiConsumer<String,String>() {
			@Override
			public void accept(String key,String value) {
				System.out.println(key + " = " + value);
			}
		});
		System.out.println("=====================");
		//最简lambda表达式
		m.forEach((key,value)->System.out.println(key + " = " + value));
	}
}

三、 Map的三种实现类

1.  HashMap

HashMap的特点:

  • HashMap是Map里面的一个实现类。
  • 没有额外需要学习的特有方法,直接使用Map里面的方法就可以。
  • 特点是由决定的: 无序、不重复、无索引
  • HashMap和HashSet底层逻辑是一样的,都是哈希表结构
  1.  依赖hashCode方法和equals方法保证键的唯一
  2. 如果存储的是自定义对象,需要重写hashCode和equals方法。
  3. 如果存储的是自定义对象,不需要重写hashCode和equals方法。

 练习: Map集合案例: 统计投票人数

需求:
某个班级80名学生,现在需要组成秋游活动,班长提供了四个景点依次是(A、B、C、D) ,每个学生只能选择一个景点,请统计出最终哪个景点想去的人数最多。

public class hashMapTest {
	public static void main(String[] args) {
		// 1.定义数组存储景点
		String[] arr = { "A", "B", "C", "D" };

		// 2.利用随机数模拟80为同学投票
		// 并将投票结果存储起来
		ArrayList<String> list = new ArrayList<>();
		Random r = new Random();
		for (int i = 0; i < 80; i++) {
			int index = r.nextInt(arr.length);
			list.add(arr[index]);
		}

		// 3.如果统计数据多 不建议使用计数器思想
		// 我们定义map集合 利用集合进行统计
		HashMap<String, Integer> map = new HashMap<>();
		for (String name : list) {
			// 判断当前的景点在map集合当中是否存在
			if (map.containsKey(name)) {
				// 存在
				// 获取当前景点已经被投票次数
				int count = map.get(name);
				count++;
				map.put(name, count);
			} else {
				map.put(name, 1);
			}
		}
		System.out.println(map);

		// 4.求最大值
		int max = 0;
		Set<Map.Entry<String, Integer>> entries = map.entrySet();
		for (Map.Entry<String, Integer> entry : entries) {
			int count = entry.getValue();
			if (count > max) {
				max = count;
			}
		}
		System.out.println(max);

		// 5. 判断哪个景点与最大值一样
		for (Map.Entry<String, Integer> entry : entries) {
			int count = entry.getValue();
			if (count == max) {
				System.out.println(entry.getKey());
			}
		}
	}
}

 2.  LinkedHashMap

  • 由键决定 有序、不重复、无索引。
  •  这里的有序指的是保证存储和取出的顺序一致
  • 原理:底层数据结构依然是哈希表,只是每个键值对元素又额外的多加了一个双链表的机制记录存储的顺序。
public class LinkedHashMapTest {
	public static void main(String[] args) {
		// 1.创建集合
		LinkedHashMap<String, Integer> lhm = new LinkedHashMap<>();

		// 2.添加元素
		lhm.put("a", 123);
		// lhm.put("a",123 );
		lhm.put("a", 111);
		lhm.put("b", 456);
		lhm.put("d", 789);

		// 3.打印集合
		System.out.println(lhm); // {a=123, b=456, d=789}
		System.out.println(lhm); // {a=111, b=456, d=789}
	}
}

3. TreeMap

  • TreeMap跟TreeSet底层原理一样,都是红黑树结构的。
  • 由键决定特性:不重复、无索引、可排序
  • 可排序:对键进行排序
  • 注意:默认按照键的从大到小进行排序,也可以自己规定键的排序规则。

代码书写的两种排序规则:

  • 实现Comparable接口,指定比较规则。
  • 创建集合时传递Comparator比较器对象,指定比较规则。

3.1 练习: TreeMap基本应用

需求:

        键:整数表示id
        值:字符串表示商品名称
        要求:按照id的升序排列、按照id的降序排列

public class TreeMapTest {
	public static void main(String[] args) {
		// 1.创建集合对象

		// Integer Double 默认情况按升序排列
		// String 按字母在ASCII 表对应数字升序排列

		TreeMap<Integer, String> tm = new TreeMap<>(new Comparator<Integer>() {
			@Override
			public int compare(Integer i1, Integer i2) {
				// i1:当前要添加的元素
				// i2:表示已经在红黑树中存在的元素
				return i2 - i1;
			}
		});

		// 2.添加商品
		tm.put(2, "康师傅");
		tm.put(1, "粤里粤");
		tm.put(3, "九个核桃");
		tm.put(5, "可恰可乐");
		tm.put(4, "雷碧");

		// 3.打印集合
		// 默认按键升序排列
		System.out.println(tm);
	}
}

3.2 练习:统计个数

需求:字符串 “aababcabcdabcde"
请统计字符串中每一个字符出现的次数,并按照以下格式输出

输出结果:
        a (5) b (4) c (3) d (2) e ( 1)

public class TreeMapTest {
	public static void main(String[] args) {
		// 1.定义字符串
		String str = "aababcabcdabcde";

		// 2.创建集合
		TreeMap<Character, Integer> tm = new TreeMap<>();

		// 2.遍历字符串得到每一个字符
		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			// System.out.println(c);
			// 将c去集合中判断是否存在
			if (tm.containsKey(c)) {
				int count = tm.get(c);
				count++;
				tm.put(c, count);
			} else {
				tm.put(c, 1);
			}
		}
		// 打印集合
		System.out.println(tm);
		// 遍历集合按照指定格式进行拼接
		StringBuilder sb = new StringBuilder();
		tm.forEach((key, value) -> sb.append(key).append("(").append(value).append(")"));
		System.out.println(sb);
		
		StringJoiner sj = new StringJoiner("","","");
		tm.forEach((key,value) -> sj.add(key + "").add("(").add(value + "").add(")"));
		System.out.println(sj);
	}
}

四、 可变参数

  1. 可变参数本质上就是一个数组
  2. 作用:在形参中接收多个数据
  3. 格式:数据类型 ... 参数名称    举例: int ... a
  4. 注意事项:
  • 形参列表中可变参数只能有一个
  • 可变参数必须放在形参列表的最后面

 案例: 可变数组的练习

假如需要定义一个方法求和,该方法可以灵活的完成如下需求:

计算2个数据的和
计算3个数据的和

计算4个数据的和

计算n个数据的和

public class Test {
	public static void main(String[] args) {
		// JDK5
		// 可变参数:方法形参个数是可变的
		// 格式: 数据类型 ... 名字

		System.out.println(getSum(1, 2, 3)); // 6
		System.out.println(getSum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); // 55
	}

	// 底层:
	// 可变参数底层就是一个数组
	// 只不过不需要我们去创建,java会自动帮我们创建好
	public static int getSum(int... args) {
		// System.out.println(args); //[I@7852e922
		int sum = 0;
		for (int i : args) {
			sum = sum + i;
		}
		return sum;
	}
}

五、Collections

  • java.util.Collections : 是集合工具类
  • 作用:Collections不是集合,而是集合的工具类。

 Collections的常用API:

方法名称说明
public static <T> boolean addAll(Collection<T> c , T... elements)批量添加元素
public static void shuffle(List<?> list)打乱List集合当中元素的顺序
public static <T> void sort(List<T> list)排序
public static <T> void sort(List<T> list,comparator<T> c)根据指定的规则进行排序
public static <T> int binarysearch (List<T> list,T key)以二分查找法查找元素
public static <T> void copy( List<T> dest,List<T> src)拷贝集合中的元素
public static <T> int fill (List<T> list,T obj)使用指定的元素填充集合
public static <T> void max/min(Collection<T> col1)根据默认的自然排序获取最大/小值
public static <T> void swap(List<?> list,int i, int j)交换集合中指定位置的元素
public class CollectionsTest {
	public static void main(String[] args) {
		// 1.创建集合对象
		ArrayList<String> list = new ArrayList<>();

		// 2.addAll 批量添加
		Collections.addAll(list, "abc", "bcd", "dwer", "df", "zxcv", "1234");
		System.out.println(list); // [abc, bcd, dwer, df, zxcv, 1234]

		// 3.shuffe 打乱顺序
		Collections.shuffle(list);
		System.out.println(list); // [zxcv, abc, 1234, bcd, df, dwer]
	}
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hgngy.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值