了解:自定义排序算法:https://www.jianshu.com/p/9334567d0912
集合和数组的区别
数组:定长的 可以存放相同类型的数据 数据可以是基本类型也可以是引用类型 访问速度比较快
集合:可变长 只能存放引用类型 访问速度比数组会稍慢一些 java.util包里
集合层次结构
集合分类
collection set list map 接口
set list map区别
set:无序的,不重复 用来去重
list:有序的,数据可以重复
map: key-value键值对方式存储的 key 不可以重复,value可以重复
hashSet按hashcode排序(无序)
@Test
public void test1(){
//先实例化
HashSet s=new HashSet();
//存放数据
s.add("liucy");
s.add("tanzy");
s.add("liucy");
s.add("zhanghs");
s.add("shenp");
//读出并打印
for(Object name:s){
System.out.println(name);
}
}
TreeSet按自然顺序(字母a-z,中文全拼顺序)
@Test
public void test2(){
//先实例化
TreeSet s=new TreeSet();
//存放数据
s.add("liucy");
s.add("tanzy");
s.add("liucy");
s.add("zhanghs");
s.add("shenp");
//读出并打印
for(Object name:s){
System.out.println(name);
}
}
@Test
public void test3(){
//先实例化
HashSet s=new HashSet();
//存放数据
s.add("liucy");
s.add("tanzy");
s.add("liucy");
s.add("zhanghs");
s.add("shenp");
//沈盼出去了
s.remove("shenp");
//查看有没有指定元素
boolean result=s.contains("shenp");
System.out.println(result);
//读出并打印
for(Object name:s){
System.out.println(name);
}
}
用泛型限制集合数据的类型
<数据类型>
@Test
public void test4(){
//先实例化
HashSet<String> s=new HashSet();
//存放数据
s.add("liucy");
s.add("liucy");
s.add("shenp");
//沈盼出去了
s.remove("shenp");
//查看有没有指定元素
boolean result=s.contains("shenp");
System.out.println(result);
//读出并打印
for(String name:s){
System.out.println(name);
}
}
retainAll 保留子集
@Test
public void test6(){
Set<String> s=new HashSet();
s.add("qinggx");
s.add("zhougb");
s.add("dddd");
s.add("ccccc");
System.out.println(s);
Set<String> white=new HashSet();
white.add("qinggx");
white.add("zhougb");
//把白名单里的人保留下来
s.retainAll(white);
System.out.println(s);
}
removeAll
@Test
public void test5(){
Set<String> s=new HashSet();
s.add("qinggx");
s.add("zhougb");
s.add("dddd");
s.add("ccccc");
System.out.println(s);
Set<String> black=new HashSet();
black.add("qinggx");
black.add("zhougb");
//把黑名单里的人从s里移除
s.removeAll(black);
System.out.println(s);
}
存放实体类
public class ClassA {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试方法
@Test
public void test5(){
ClassA a=new ClassA();
a.setId(16);
a.setName("java16");
ClassA b=new ClassA();
b.setId(7);
b.setName("java7");
//先实例化
HashSet<ClassA> s=new HashSet();
s.add(a);
s.add(b);
for(ClassA c:s){
System.out.println(c.getId()+" "+c.getName());
}
}
Iterator 迭代器#
@Test
public void test6() {
ClassA a = new ClassA();
a.setId(16);
a.setName("java16");
ClassA b = new ClassA();
b.setId(7);
b.setName("java7");
// 先实例化
HashSet<ClassA> s = new HashSet();
s.add(a);
s.add(b);
//得到迭代器
Iterator i=s.iterator();
//hasNext() 有没有下一次元素 布尔型
while(i.hasNext()){
//next()方法取出
ClassA c=(ClassA)i.next();
System.out.println(c.getName());
System.out.println(c.getId());
}
}
[如何边遍历集合边删除元素--使用Iterator中的remove()方法]
否则会引发ConcurrentModifactionException()
@Test
public void test1(){
Set<String> s=new HashSet();
s.add("a");
s.add("c");
s.add("b");
Iterator i=s.iterator();
while(i.hasNext()){
String str=(String) i.next();
//如果str为a就移除
if("a".equals(str)){
//错误写法s.remove(str);
//正确
i.remove();
}
}
System.out.println(s);
}
课堂练习
使用Set集合,生成1-25之内不重复的7个随机整数
@Test
public void test11() {
HashSet<Integer> hs = new HashSet();
for (;;) {
int r = new Random().nextInt(25) + 1;
hs.add(r);
if (hs.size() == 7) {
System.out.println(hs);
break;
}
}
}
@Test
// 使用Set集合,生成1-25之内不重复的7个随机整数
public void try05() {
HashSet<Integer> hs = new HashSet();
int count = 0;
while (count < 7) {
Integer j = new Random().nextInt(25) + 1;
if (hs.add(j)) {
count++;
}
}
for (Integer i : hs) {
System.out.println(i);
}
}
public class test {
public static void main(String[] args) {
HashSet<Integer> h=new HashSet<>();
while (h.size()<7){
h.add((int)(Math.random()*25+1));
}
System.out.println(h);
}
}
List
List:ArrayList(常用) LinkedList Vector(线程安全)
ArrayList:有序的 可重复 底层是基于数组实现的 随机读取时速度快 适合做查询
LinkedList:底层是基于链接实现的 可以用来做栈和队列,特点是:插入和删除快,查询慢
Vector:线程安全的 做线程同步,速度会慢
栈:先进后出(类似给枪压子弹)
队列:先进先出 queue
@Test
public void test() {
List<String> s=new ArrayList();
s.add("liucy");
s.add("tanzy");
s.add("liucy");
s.add("zhanghs");
s.add("shenp");
for(String name:s){
System.out.println(name);
}
}
@Test
public void test5() {
ClassA a = new ClassA();
a.setId(16);
a.setName("java16");
ClassA b = new ClassA();
b.setId(7);
b.setName("java7");
// 先实例化
List<ClassA> s = new ArrayList();
s.add(a);
s.add(b);
for (ClassA c : s) {
System.out.println(c.getId() + " " + c.getName());
}
}
ListIterator
先正向再反向读
@Test
public void test2() {
List<String> s=new ArrayList();
s.add("liucy");
s.add("tanzy");
s.add("liucy");
s.add("zhanghs");
s.add("shenp");
//正向输出
ListIterator i=s.listIterator();
while(i.hasNext()){
System.out.println(i.next());
}
System.out.println("------------------->");
//反向输出
while(i.hasPrevious()){
System.out.println(i.previous());
}
}
上面的代码如果把正向的注释掉,反向的也读不出来,原因是指针在最上面,解决方式是可以在listIterator参数里把size大小加进去。让指针先跳转到指定位置
@Test
public void test3() {
List<String> s=new ArrayList();
s.add("liucy");
s.add("tanzy");
s.add("liucy");
s.add("zhanghs");
s.add("shenp");
//读取第3个元素
String ss=s.get(3);
System.out.println("第三个"+ss);
//正向输出
ListIterator i=s.listIterator(s.size());
System.out.println("------------------->");
//反向输出
while(i.hasPrevious()){
System.out.println(i.previous());
}
}
LinkedList常用操作
新增方法:addFirst() addLast() getFirst() getLast() removeFirst() removeLast()
addFirst() addLast()例子:
@Test
public void test() {
LinkedList<String> s = new LinkedList();
s.add("liucy");
s.add("tanzy");
s.add("liucy");
s.add("zhanghs");
s.add("shenp");
// addFirst从顶面add
s.addFirst("NUMER ONE");
// addLast以底部add
s.addLast("我是倒数第一");
s.removeFirst();
s.removeFirst();
s.removeLast();
for (String name : s) {
System.out.println(name);
}
}
Collections类
@Test
public void test01() {
// 1、求最大值
List<Integer> list01 = new ArrayList();
list01.add(20);
list01.add(25);
list01.add(19);
list01.add(27);
list01.add(28);
// 作业:Collections(list,com)
//Integer maxAge = Collections.max(list01);
//System.out.println(maxAge);
//Integer minAge = Collections.min(list01);
//System.out.println(minAge);
//reverse 28, 27, 19, 25, 20 只是把顺序进行了简单的反转
//Collections.reverse(list01);
//System.out.println("reverse之后的集合:"+list01);
//sort从小到大排序
//list01里的数据永远变动
Collections.sort(list01);
System.out.println("sort之后的集合:"+list01);
//binarySearch 查询集合中是否存在指定的元素
//19时-2 28-4
//19-0 20 25-2 27 28-4
//如果查找的对象存在,返回排序的对象索引 0
// 如果不存在,就返回负数
System.out.println(list01);
//在变化后的list01中进行操作
int result=Collections.binarySearch(list01, 23);
System.out.println("查找结果"+result);
//fill copy
// 用list02的值覆盖
Collections.copy(list01, list02);
// Collections.copy(list02, list01);
System.out.println("copy后list01-->" + list01);
System.out.println("copy后list02-->" + list02);
}
今天在学习集合中 有关对象的深度拷贝和浅拷贝 的时候,像拷贝一个ArrayList对象到另一个ArrayList对象中,正好发现Collections有一个copy方法。可是不好用啊总是报错。查看api才知道,它的capacity(容纳能力大小)可以指定(最好指定)。而初始化时size的大小永远默认为0,只有在进行add和remove等相关操作 时,size的大小才变化。然而进行copy()时候,首先做的是将desc的size和src的size大小进行比较,只有当desc的 size 大于或者等于src的size时才进行拷贝,否则抛出IndexOutOfBoundsException异常;
//想拷贝list01到list02
//复制了解即可
@Test
public void test02() {
List<String> list01 = new ArrayList<String>();
list01.add("111");
list01.add("222");
list01.add("333");
list01.add("444");
List<String> list02 = new ArrayList<String>();
Collections.addAll(list02, new String[list01.size()]);
Collections.copy(list02, list01);
System.out.println(list02);
}
@Test
public void test02() {
List<String> list01 = new ArrayList<String>();
list01.add("111");
list01.add("222");
list01.add("333");
list01.add("444");
List<String> list02 = new ArrayList<String>();
list02.addAll(list01);
System.out.println(list01);
System.out.println(list02);
list01.add("555");
System.out.println(""+list01);
System.out.println(list02);
}
课堂练习:试验collections其他方法
作业:
1、请使用LinkedList来模拟一个队列(先进先出的特性): [必做题]
1.1 拥有放入对象的方法void put(Object o)
1.2 取出对象的方法Object get()
1.3 判断队列当中是否为空的方法boolean isEmpty();并且,编写测试代码,验证你的队列是否正确。
2、产生10个1-100的随机数,并放到一个数组中,把数组中大于等于10的数字放到一个list集合中,并打印到控制台。
3、双色球规则:双色球每注投注号码由6个红色球号码和1个蓝色球号码组成。红色球号码从1—33中选择;蓝色球号码从1—16中选择;请随机生成一注双色球号码。(要求同色号码不重复)
map
Map :key-value
map:HashMap基于哈希的 TreeMap基于红黑树的 LinkedHashMap
@Test
public void test1() {
ClassA a = new ClassA();
a.setId(16);
a.setName("java16");
ClassA b = new ClassA();
b.setId(7);
b.setName("java7");
// 新建一个map
Map<String, ClassA> map = new HashMap();
// 向map里存放数据put方法
map.put("c7", b);
map.put("c16", a);
// 单个读取
// 我知道key的情况下,根据key去查询。用get方法
// 比如我想读取编号为c16的班级的信息
ClassA c16 = map.get("c16");
System.out.println(c16.getId() + c16.getName());
//如果get里的key不存在,就会抛异常NullPointer空指针异常
//所以在根据key读取时,最好先判断有没有
if(map!=null&&!map.isEmpty()){
if(map.containsKey("c17")){
ClassA c17 = map.get("c17");
System.out.println(c17.getName());
}else{
System.out.println("不存在这个key的数据");
}
}
}
再来一个例子 模拟存储最后位置
public class Point {
//纬度41.8
private double lat;
//经度123.4
private double lon;
public Point(double lat, double lon) {
super();
this.lat = lat;
this.lon = lon;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLon() {
return lon;
}
public void setLon(double lon) {
this.lon = lon;
}
}
// 1)创建:构造方法指定初始化个数或不指定初始化次数 new HashMap()--默认是初始化10 new HashMap(8) --掌握
// 2)添加: 单个添加put(key,value) --掌握
// 批量添加:putAll(Map t)
// 3)修改: 单个put(key,value) 批量:putAll(Map t) 相同key的覆盖原有的。
// 4)删除: clear() --删除所有
// remove(key) --删除指定key的一条数据
// 5)查询单个:get(key) 利用key取出value --掌握
// containsKey(key)是否存在指定key --掌握
// containsValue(value) 是否存在指定value ---了解
// 查询所有:size()-一共几条
// isEmpty()是否为空
// keyset-有哪些key ---难 了解
// entryset-(key,value) ---难 了解
@Test
public void test03() {
// 根据手机号码,查询最后位置
// step1 建立一个point实体
// 沈阳的经纬度lon= 123.4 lat=41.8
// step2 建一个map用于存放手机号及该手机号的最后位置
// map<手机号,最后位置>
Map<String, Point> lastPosMap = new HashMap();
// step3 向map里放每个人的最后位置
Point p1 = new Point(41.8, 123.4);
lastPosMap.put("13904001139", p1);
// 一口气写法
lastPosMap.put("13840191050", new Point(40.9, 123.42));// 王哥
lastPosMap.put("13840191051", new Point(41.9, 123.445));
// 假设这个人动了,就再上报一次位置
lastPosMap.put("13840191050", new Point(40.92, 123.423));// 王哥 131行的被覆盖
// 查询指定手机号的最后位置
// 能不能孙宇的最后位置
if (lastPosMap.containsKey("18695876927")) {// 是否存在18695876927的最后位置信息呢
System.out.println("有孙宇的最后位置");
} else {
System.out.println("对不起,没查到");
}
if (lastPosMap.containsKey("13840191050")) {// 是否存在18695876927的最后位置信息呢
// 如果可以查到,我就可以通过get(key)方法把王浩丞的最后位置拿到。在地图上描画
Point wanglast = lastPosMap.get("13840191050");
// 打印一下位置里的详细信息
System.out.println("王浩丞的位置信息" + wanglast.getLat() + " " + wanglast.getLon());
}
// 上面的方法比较常用 必须熟练掌握的
// 接下来的方法 练习
}
// 以下这些不常用 了解
@Test
public void test04() {
// 4)删除: clear() --删除所有--比较常用 delete 不带条件
Map<String, Point> lastPosMap = new HashMap();
// step3 向map里放每个人的最后位置
Point p1 = new Point(41.8, 123.4);
lastPosMap.put("13904001139", p1);
// 一口气写法
lastPosMap.put("13840191050", new Point(40.9, 123.42));// 王哥
lastPosMap.put("13840191051", new Point(41.9, 123.445));
//lastPosMap.clear();
//System.out.println("删除数据后的map"+lastPosMap);
// remove(key) --删除指定key的一条数据 --比较常用
//lastPosMap.remove("13904001139");//delete from 表名 where key=?
//System.out.println("删除数据后的map"+lastPosMap);
// 5)查询单个:
// containsValue(value) 是否存在指定value ---了解即可 不常用
//Point p1 = new Point(41.8, 123.4);
//lastPosMap.put("13904001139", p1);
Point p4 = new Point(41.8, 123.4);
lastPosMap.put("13904001139", p4);
if(lastPosMap.containsValue(p1)){//true/false
System.out.println("存在");
}else{
System.out.println("不存在");
}
// 查询所有:size()-一共几条--比较常用
System.out.println("map里有几条数据:"+lastPosMap.size());
// isEmpty()是否为空
if(lastPosMap.isEmpty()){
System.out.println("为空");
}else{
System.out.println("不为空");
}
}
map循环
第一种:循环keySet,然后通过key读取value
@Test
public void test05() {
// keyset-有哪些key ---难了解
// entryset-(key,value) ---难 优先掌握
Map<String, Point> lastPosMap = new HashMap();
// step3 向map里放每个人的最后位置
Point p1 = new Point(41.8, 123.4);
lastPosMap.put("13904001139", p1);
// 一口气写法
lastPosMap.put("13840191050", new Point(40.9, 123.42));// 王哥
lastPosMap.put("13840191051", new Point(41.9, 123.445));
//查询所有,有两种方式keyset
//step1
Set<String> keys=lastPosMap.keySet();//所在key的集合
//用加强for,循环到每个key
for(String name:keys){
System.out.println(name);
//step2 用key获取value
Point p=lastPosMap.get(name);
System.out.println(p.getLat()+" "+p.getLon());
}
}
// entryset-(key,value) ---难 优先掌握
@Test
public void test06() {
// keyset-有哪些key ---难了解
// entryset-(key,value) ---难 优先掌握
Map<String, Point> lastPosMap = new HashMap();
// step3 向map里放每个人的最后位置
Point p1 = new Point(41.8, 123.4);
lastPosMap.put("13904001139", p1);
// 一口气写法
lastPosMap.put("13840191050", new Point(40.9, 123.42));// 王哥
lastPosMap.put("13840191051", new Point(41.9, 123.445));
//通过循环entryset来获取entry(key,value)
Set<Entry<String,Point>> s=lastPosMap.entrySet();
//循环entry实体,就可以拿到key value
for(Entry<String,Point> p:s){
String phone=p.getKey();
Point lp=p.getValue();
System.out.println(lp.getLat()+" " +lp.getLon());
}
}
treeMap key顺序 字母a-Z 数学按大学排序
@Test
public void test08() {
Map<Integer, Point> lastPosMap = new TreeMap();
// step3 向map里放每个人的最后位置
Point p1 = new Point(41.8, 123.4);
lastPosMap.put(140, p1);
lastPosMap.put(139, new Point(41.9, 123.445));
// 一口气写法
lastPosMap.put(150, new Point(40.9, 123.42));// 王哥
//通过循环entryset来获取entry(key,value)
Set<Entry<Integer,Point>> s=lastPosMap.entrySet();
//循环entry实体,就可以拿到key value
for(Entry<Integer,Point> p:s){
Integer phone=p.getKey();
Point lp=p.getValue();
System.out.println(phone+" "+lp.getLat()+" " +lp.getLon());
}
}
作业:
/**
* 1、请使用LinkedList来模拟一个队列(先进先出的特性): [必做题]
* 1.1 拥有放入对象的方法void put(Object o)
* 1.2 取出对象的方法Object get()
* 1.3 判断队列当中是否为空的方法boolean isEmpty();
* 并且,编写测试代码,验证你的队列是否正确。
*/
public class MyQueue {
//类级别定义一个LinkedList类型的变量
LinkedList queue=new LinkedList();
public void put(Object o){
queue.addFirst(o);
}
public Object get(){
Object obj=queue.getLast();
queue.removeLast();
return obj;
}
public boolean isEmpty(){
return queue.isEmpty();
}
public static void main(String[] args) {
MyQueue mq=new MyQueue();
mq.put("hello1");
mq.put("hello2");
mq.put("hello3");
while(!mq.isEmpty()){
Object o=mq.get();
System.out.println(o);
}
}
}
2、产生10个1-100的随机数,并放到一个数组中, 把数组中大于等于10的数字放到一个list集合中,并打印到控制台
3、双色球规则:双色球每注投注号码由6个红色球号码和1个蓝色球号码组成。
红色球号码从1―33中选择;蓝色球号码从1―16中选择;请随机生成一注双色球号码。
(要求同色号码不重复)