集合
- 例题引入——直线
- 题意分析
- 根据下面的参考代码,自己模仿的
- 参考代码(加一点点我的小tips)
- ============================================
- 1.java集合引入
- 2.为什么要使用集合?
- 3.List、Set、Queue和Map的区别
- 4.List
- List——ArrayList
- (!!实用!!)ArrayList常用方法
- List——Vector
- List——LinkedList
- 5.Set
- 6.Map
- HashMap
- HashSet
- entrySet
- 参考文档
最近总遇到要用 Map 的题
这里写一下我的学习笔记
主要参考来自github–JavaGuide项目(超超超超超级推荐!!!)
(文章最后会附上链接)
例题引入——直线
在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上,那么这些点中任意两点确定的直线是同一条。
题意分析
- 重点:直线—》怎么确定一条直线?—》直线方程 y = kx +b —》k,b确定一条直线
- 直线不重复–》想到要用Set集合—》用HashSet(重复的元素根本就不会存进去)
- 求k,b!!!这我竟然忘了咋求了!!
根据下面的参考代码,自己模仿的
import java.util.*;
//import java.util.Map.Entry;
//import com.sun.org.apache.bcel.internal.generic.IINC;
public class Main{
public static void main(String[] args) {
//创建 HashSet集合,存放 k,b
HashSet<Map<Double, Double>> sets = new HashSet<>();
//创建 ArrayList集合 ,存放 点坐标
ArrayList<Map<Integer, Integer>> list = new ArrayList<>();
for(int i=0;i<20;i++) {
for(int j=0;j<21;j++) {
Map<Integer, Integer> map = new HashMap<>();
map.put(i, j);
list.add(map); //点坐标放到ArrayList中
}
}
//遍历ArrayList,计算其对应的k和b
double x1 = 0,y1 = 0,x2 = 0,y2 = 0; //要定义为double类型--》后面要用点坐标 计算k和b的值
for(int i=0;i<list.size();i++) {
//对于list集合中的每一个点,都去与它后面的所有点连线
for(int j=i+1;j<list.size();j++) {
//计算两点确定的一条直线的k,b
//获取两点坐标
for(Map.Entry<Integer, Integer> entry : list.get(i).entrySet()) {
x1 = entry.getKey();
y1 = entry.getValue();
}
for(Map.Entry<Integer, Integer> entry : list.get(j).entrySet()) {
x2 = entry.getKey();
y2 = entry.getValue();
}
//先不计算平行于x轴和y轴的那些直线
if(x1 == x2 || y1 == y2) {
continue;
}
//根据坐标点 计算k,b
double k = (y1-y2)/(x1-x2);
double b = (y1*x2-y2*x1)/(x2-x1);
//创建一个临时的map--》打包k,b
HashMap<Double,Double> temp = new HashMap<>();
temp.put(k, b);
//把map放到HashSet集合中---》Set集合天然的不添加重复元素---》最后Set集合的长度就是kb对的长度--》也就是确定唯一直线的个数
sets.add(temp);
}
}
System.out.println(sets.size()+20+21);
}
}
参考代码(加一点点我的小tips)
代码参考于 蓝桥官网—— “求求你别黑我家哥哥了” 大佬
import java.util.*;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
HashSet<Map<Double,Double>> lines = new HashSet<>();
List<Map<Integer,Integer>> list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 21; j++) {
//map中存放的kv对是点坐标
Map<Integer,Integer> map = new HashMap<>();
map.put(i,j);
//再把map放到list中。也就是说,现在list中每一个index 存放的都是一个map集合(就是一个kv对表示的坐标点x,y)
list.add(map);
}
}
//得到两个直线点
double x1=0,x2=0,y1=0,y2=0;
//从list.get(0)开始,遍历每一个 index=0 之后的点 (也就是两点连线)
for (int i = 0; i < list.size(); i++) {
for (int j = i+1; j < list.size(); j++) {
//得到i中的map的kv对的值(也就是出发点的坐标k=x,v=y)
for (Map.Entry<Integer, Integer> entry : list.get(i).entrySet()) {
x1 = entry.getKey();
y1 = entry.getValue();
}
//同理,得到j中的map(k,v)
for (Map.Entry<Integer, Integer> entry : list.get(j).entrySet()) {
x2 = entry.getKey();
y2 = entry.getValue();
}
//先不计算所有平行于x轴,y轴的直线
if (x1 == x2 || y1 == y2) {
continue;
}
//计算出 这两点对应的k,b的值
double k = (y2 - y1) / (x2 - x1);
double b = (x2 * y1 - x1 * y2) / (x2 - x1);
//k,b值存放到一个map集合中
Map<Double, Double> temp = new HashMap<>();
temp.put(k, b);
//把这个map集合放到HashSet集合中--》自动的 重复的k,b只会存进去一次
lines.add(temp);
}
}
//最后,lines中有多少个map集合,那就有多少条不重复的直线---》这里需要加上之前刨除的平行于x轴和y轴的那些直线
System.out.println(lines.size()+20+21);
}
}
基于这段代码,开启这篇文章
============================================
1.java集合引入
java集合,也叫做容器,主要是由两大接口派生而来:
Collection接口,用于存放单一元素;
Map集合,主要存放键值对。
对于Collection接口,下面又有三个主要的子接口:List、Set和Queue
- java集合框架(概览)如下:
2.为什么要使用集合?
当我们需要存储一组类型相同的数据时,数组是最常用且最基本的容器之一。但是,使用数组存储对象存在一些不足之处,因为在实际开发中,存储的数据类型多种多样且数量不确定。这时,Java
集合就派上用场了。与数组相比,Java 集合提供了更灵活、更有效的方法来存储多个数据对象。Java
集合框架中的各种集合类和接口可以存储不同类型和数量的对象,同时还具有多样化的操作方式。相较于数组,Java
集合的优势在于它们的大小可变、支持泛型、具有内建算法等。总的来说,Java
集合提高了数据的存储和处理灵活性,可以更好地适应现代软件开发中多样化的数据需求,并支持高质量的代码编写。
3.List、Set、Queue和Map的区别
简单的说:
- List:有顺序
- Set:元素不可重复
- Queue:排队
- Map:用key来搜索value
- List:存储的元素都是有序的、可重复的
- Set:存储的元素不可重复
- Queue:按特定的排队规则来确定先后顺序,存储的元素是有序的、可重复的
- Map:使用键值对(key-value)存储,类似于数学上的函数y=f(x),“x”代表key,“y”代表value。key是无序的、不可重复的;value是无序的、可重复的,每个键最多映射到一个值。
4.List
- ArrayList
- Vector
- LinkedList
List——ArrayList
- ArrayList的底层是数组队列,相当于动态数组。
- 与java中的数组相比,它的容量能动态增长。
- 在添加大量元素前,应用程序可以使用ensureCapacity操作来添加ArrayList实例的容量
- ArrayList 继承于AbstractList,实现了List,RandomAccess,Cloneable,java.io.Serializable这些接口。
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
}
- ArrayList实现的功能也和这些接口有关
- List:表明它是一个列表,支持添加、删除、查找等操作,并且可以通过下标进行访问。
- RandomAccess:这是一个标志接口,表明实现这个接口的List集合是支持快速随机访问的。在ArrayList中,我们既可以通过元素的序号快速获取元素对象,这就是快速随机访问。
- Cloneable:表明它具有拷贝能力,可以进行深拷贝或浅拷贝操作。
- Serializable:表明它可以进行序列化操作,也就是可以将对象转换为字节流进行持久化存储或网络传输。
(!!实用!!)ArrayList常用方法
- add(E element):将指定元素添加到列表的末尾
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(123);
list.add(45);
list.add(666);
System.out.println(list); //output:[123, 45, 666]
ArrayList<String> s = new ArrayList<String>();
s.add("hfies");
s.add("jeif");
s.add("fose");
System.out.println(s); //output:[hfies, jeif, fose]
- add(int index,E element):在指定位置插入指定元素
list.add(2, 9999);
System.out.println(list); //output:[123, 45, 9999, 666]
- get(int index):返回指定位置的元素
System.out.println(list.get(2)); //output:9999
//也可用于循环输出
for(int i=0;i<list.size();i++) {
System.out.print(list.get(i)+" "); //output:123 45 9999 666
}
- set(int index,R element):替换指定位置的元素
list.set(2, 8888);
System.out.println(list);//output:[123, 45, 8888, 666]
- remove(int index):移除指定位置的元素
list.remove(2);
System.out.println(list);//output:[123, 45, 666]
- size():返回列表中的元素数目
System.out.println(list.size());//output:3
- clear():清空列表中的所有元素
list.clear();
System.out.println(list);//output:[]
- contains(Object o):判断列表是否包含指定元素
System.out.println(list.contains(666));//output:true
- indexOf(Object o):返回指定元素在列表中第一次出现的位置
System.out.println(list.indexOf(45));//output:1
- isEmpty():判断列表是否为空
System.out.println(list.isEmpty());//output:false
- clone():复制数组
Object o = list.clone();
System.out.println(o);//output:[123, 45, 666]
- 全部代码:
import java.util.*;;
public class Main{
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(123);
list.add(45);
list.add(666);
System.out.println(list); //output:[123, 45, 666]
ArrayList<String> s = new ArrayList<String>();
s.add("hfies");
s.add("jeif");
s.add("fose");
System.out.println(s); //output:[hfies, jeif, fose]
list.add(2, 9999);
System.out.println(list); //output:[123, 45, 9999, 666]
System.out.println(list.get(2)); //output:9999
for(int i=0;i<list.size();i++) {
System.out.print(list.get(i)+" "); //output:123 45 9999 666
}
System.out.println();
list.set(2, 8888);
System.out.println(list);//output:[123, 45, 8888, 666]
list.remove(2);
System.out.println(list);//output:[123, 45, 666]
System.out.println(list.size());//output:3
System.out.println(list.contains(666));//output:true
System.out.println(list.indexOf(45));//output:1
System.out.println(list.isEmpty());//output:false
Object o = list.clone();
System.out.println(o);//output:[123, 45, 666]
list.clear();
System.out.println(list);//output:[]
}
}
//output:
List——Vector
List——LinkedList
这两个我还没用到过,用到会来补充
5.Set
HashSet:无序,唯一
TreeSet:有序,唯一
LinkedHashSet
- HashSet:基于HashMap实现的,底层采用HashMap来保存元素。
- LinkedHashSet:LinkedHashSet是HashSet的子类,并且其内部是通过LinkedHashMap来实现的。
- TreeSet:红黑树(自平衡的排序二叉树)
6.Map
HashMap
- map.put()
Map<Integer,String> map = new HashMap<>();
map.put(1, "1a");
map.put(2, "2a");
map.put(3, "3a");
System.out.println(map); //output:{1=1a, 2=2a, 3=3a}
//当给map中添加元素,会返回key对应的原来的value值;若key没有对应的值,返回null
System.out.println(map.put(1, "5")); //output:1a
System.out.println(map); //output:{1=5, 2=2a, 3=3a}
- map.get()
//根据指定的key获取对应的value
String s = map.get(2);
System.out.println(s); //output:2a
- map.remove()
//根据key删除元素,会返回key对应的value值
String value = map.remove(2);
System.out.println(value); //output:2a
System.out.println(map); //output:{1=5, 3=3a}
HashSet
HashSet是基于HashMap来实现的,实现了Set接口,同时还实现了序列化和可克隆化。
而集合Set是不允许有重复值的。
所以HashSet是一个没有重复元素的集合,但不保证集合的迭代顺序(所以,随着时间改变,元素的顺序可能会改变)
由于HashSet是基于HashMap来实现的,所以允许空值,不是线程安全
-
HashSet是基于HashMap实现的,区别就在于HashMap中输入一个键值对,而在HashSet中只输入一个值。
-
构建HashSet
HashSet<E> hs = new HashSet<E>();
//也可以写成
Set<E> hs = new HashSet<E>();
- add():因为HashSet不会存在重复元素,所以相同的元素不会存进去
- 常用方法:
entrySet
entrySet就是用来遍历map的一种方法
entrySet是java中键值对的集合,Set里面的类型是Map.Entry,一般可以通过map.entrySet()得到。
- entrySet实现了Set接口,里面存放的是键值对。
Set<Map.Entry<String,String>> entryseSet = map.entrySet();
for(Map.Entry<String,String> entry:entryseSet){
System.out.println("key= ” + entry.getKey + "," + "value= " + entry.getValue()):
}
参考文档
- java笔记–Map的用法
- Java中哈希集(HashSet)概念,实现以及操作