0%

    本文首发于cartoon的博客

    转载请注明出处:https://cartoonyu.github.io/cartoon-blog

    上一篇文章中我在集合元素的遍历中已经有涉及到Iterator的普遍使用方法,但是并没有对此进行解释。
    其实,Iterator来源于java.util包,也是属于Java集合框架中的一份子,不同于Collection(存放单一数据)和Map(存放具有映射关系的数据),Iterator主要用于集合元素的迭代输出,所以它的对象又被称为迭代器。

    Iterator的方法包括:

成员方法 作用
boolean hasNext(); 判断迭代器是否还有未遍历的元素
E next(); 返回迭代器中下一未遍历元素
void remove(); 移除迭代器上一遍历的元素
void forEachRemaining(Consumer action) 以特定的Lambda表达式遍历元素

注:void forEachRemaining(Consumer action)为Java 8新增的默认方法。

    下面是Iterator的实例化以及各方法的使用方法

  • Iterator的实例化

    1
    Iterator it=c5.iterator();

        Iterator本身不存在容纳对象的能力,它的对象必须依附于Collection对象。
    同时,一个Iterator对象只能使用一次,复用会导致java.util.ConcurrentModificationException。我还没搞懂为什么会这样,应该是关于设计模式的内容。

  • boolean hasNext();以及next();

    1
    2
    3
    while(it.hasNext()) {
    System.out.println(it.next());
    }
    1
    输出:5
  • void remove();

    1
    2
    3
    4
    while(it.hasNext()) {
    System.out.println(it.next());
    it.remove();
    }
    1
    输出:5

        remove方法要在next方法之后调用,次序调换会导致java.lang.IllegalStateException

  • void forEachRemaining(Consumer action);

    1
    2
    Iterator it=c5.iterator();
    it.forEachRemaining(obj->System.out.println(obj));
    1
    输出:5

        通过特定的Lambda表达式格式输出元素。

     Iterator接口就写到这里了。通常我都是用它作为测试Collection对象的,好处就是不用通过循环遍历,代码量会少一点。但是正式使用我还是会使用循环遍历Collection对象,虽则代码量多,但是可以省掉一个对象的内存空间,能省一点是一点,哈哈!

    如果你还想了解关于java集合的内容,欢迎点击JAVA集合概述

    本文首发于cartoon的博客

    转载请注明出处:https://cartoonyu.github.io/cartoon-blog

    在概述里面也说过:Collection是java集合两大接口之一,旗下有三大子接口:Set(元素不能重复,且无序)、Queue、List(元素可重复,且有序)。

    Collection来源于java.util包,主要方法包括:

Iterator的方法包括:

成员方法 作用
boolean hasNext(); 将传入的Object对象添加到容器中,添加后方法返回true
boolean addAll(Collection c) 将传入的集合c中的所有对象添加到容器中,添加后方法返回true
void clear() 清空集合,集合长度变为0
boolean contains(Object o) 检查集合是否存在对象o,若存在返回true
boolean containsAll(Collection c) 检查集合是否存在集合c的所有对象,若存在返回true
boolean isEmpty() 返回集合的size是否为0
Iterator iterator() 返回Iterator对象
boolean remove(Object o) 删除集合中第一个符合条件的元素,若集合存在对象o,删除并返回true
boolean removeAll(Collection c) 删除集合中所有与集合c重合的元素,若删除后对象进行了改变返回true
boolean retainAll(Collection c) 删除集合中所有与集合c不重合的元素,若删除后对象进行了改变返回true
int size() 返回集合元素的个数
Object[] toArray() 把集合转变成数组,集合的元素变成对应的数组元素

    下面是Collection的实例化以及各成员方法的使用方法

  • 实例化
1
2
3
4
5
6
Collection c1=new TreeSet();   
Collection c2=new HashSet();
Collection c3=new LinkedHashSet();
Collection c4=new ArrayDeque();
Collection c5=new ArrayList();
Collection c6=new LinkedList();
  • boolean isEmpty();
1
2
boolean isEmpty=c5.isEmpty();
System.out.print(isEmpty?"c5为空":"c5不为空");
1
输出: c5为空

    因为c5在此之前并没有添加任何元素,所以为空。

  • Iterator iterator();
1
2
3
4
Iterator it5=c5.iterator();
while(it5.hasNext()) {
System.out.println("集合5元素:"+it5.next());
}
1
输出:集合5元素:5

    注:每个Iterator对象只能使用一次, 复用会导致java.util.ConcurrentModificationException。

    在本代码中,新建了一个局部变量it5保存c5的迭代器,再通过迭代器的成员方法hasNext判断是否存在下一元素,若true,输出此元素。

    java8为Collection的遍历新增了一个来源于Collection的父接口iterable的方法:forEach(Consumer action)。

1
c5.forEach(obj->System.out.println("集合元素为"+obj));
1
输出:集合元素为5
  • boolean add(Object o);
1
2
3
4
5
c5.add(5);
Iterator it=c5.iterator();
while(it.hasNext()) {
System.out.println("集合元素:"+it.next());
}
1
输出:集合元素:5

    在本代码中,c5被添加了一个元素5,所以经过迭代器输出只能得到5。

  • boolean addAll(Collection c);
1
2
3
4
5
c6.addAll(c5);
Iterator it6=c6.iterator();
while(it6.hasNext()) {
System.out.println("集合6元素:"+it6.next());
}
1
输出:集合6元素:5

    在本代码中,c5中的所有元素(5)被整体添加到c6中,所以c6迭代输出5。

  • void clear();
1
2
3
4
5
c6.clear();
Iterator it6=c6.iterator();
while(it6.hasNext()) {
System.out.println("集合6元素:"+it6.next());
}
1
无输出

    在本代码中,c6被清空,所以迭代输出并没有结果。

  • boolean contains(Object o);
1
2
3
4
boolean isContainsFive=c5.contains(5);
boolean isContainsSix=c5.contains(6);
System.out.println("c5是否存在元素5:"+isContainsFive);
System.out.println("c5是否存在元素6:"+isContainsSix);
1
2
输出:c5是否存在元素5:true
c5是否存在元素6:false

    在本代码中,isContainsFive的值取决于c5是否含有元素5(isContainsSix亦是如此)。而c5只有一个元素5,所以isContainsFive的值为true,isContainsSix的值为false。

  • boolean containsAll(Collection c);
1
2
3
4
c4.addAll(c5);
System.out.println("c5是否包括c6的全部元素:"+c5.containsAll(c4));
c4.add(3);
System.out.println("c5是否包括c6的全部元素:"+c5.containsAll(c4));
1
2
输出:c5是否包括c6的全部元素:true
c5是否包括c6的全部元素:false

    在本代码中,首先将c5的所有元素(5)添加到c4中,所以第一个输出语句必定为true。但是在第一个语句后c4添加了一个新的元素3,所以第二个输出语句为false。

  • boolean remove(Object o);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    c5.add(6);
    Iterator it5=c5.iterator();
    while(it5.hasNext()) {
    System.out.println("集合元素:"+it5.next());
    }
    c5.remove(6);
    Iterator aIt5=c5.iterator();
    while(aIt5.hasNext()) {
    System.out.println("集合5元素:"+aIt5.next());
    }
    1
    2
    3
    输出:集合5元素:5
    集合5元素:6
    集合5元素:5

        在本代码中,c5首先添加了一个新元素6,迭代输出得到5、6。然后调用c5的成员方法remove,迭代输出得到5。

  • boolean removeAll(Collection c);

1
2
3
4
5
c5.removeAll(c4);
Iterator aIt5=c5.iterator();
while(aIt5.hasNext()) {
System.out.println("集合5元素:"+aIt5.next());
}
1
无输出

    在本代码中,c5移除掉c4中的所有元素(3、5),可以理解为移除掉两个集合的交集,所以迭代输出没有结果。

  • boolean retainAll(Collection c);
1
2
3
4
5
6
c5.add(5);
c4.retainAll(c5);
Iterator it4=c4.iterator();
while(it4.hasNext()) {
System.out.println("集合4元素:"+it4.next());
}
1
输出:集合4元素:5

    注:因为在方法9中集合5已经变成空集合,所以在此方法中将5添加到集合5中以做演示。
    在本方法中,c5添加了一个元素5,然后调用c4的成员方法retainAll删除掉不属于c5的所有元素,迭代输出5。

  • int size();
1
2
int size=c4.size();
System.out.println("集合4的元素个数为:"+size);
1
输出:集合4的元素个数为:1

    在本代码中,新建一个局部变量size保存c4的成员方法size返回的值,输出得到1(因为c4只有一个元素5)。

  • Object[] toArray();
1
System.out.println(c4.toArray());
1
输出:[Ljava.lang.Object;@71e7a66b

    作为对比,我尝试调用父类Object的String toString()方法,结果得到了[5],与直接输出对象的结果是一致的。

    注:若遍历集合的同时改变集合,将引发ConcurrentModificationException异常。

    Collection接口就写到这里了,看起来简单,但是某些成员方法需要查看源码才知道如何去用,基本上写完这篇博文,我对Collection已经有了比较深入的了解,忽然觉得写作跟编程是相辅相成的。

    一点题外话:这是我第一次系统地写博文,懂得了一个道理:世界上没有简单的事。写的不好请多多见谅。之后要狠狠提高一下我的写作水平,之前写公众号的文笔都不知道丢在哪里了。
    如果你还想了解关于java集合的内容,欢迎点击JAVA集合概述

    本文首发于cartoon的博客

    转载请注明出处:https://cartoonyu.github.io/cartoon-blog

    近段时间在学习java集合,原本也没想着写笔记或者博客的。但是慢慢看下去之后发现java集合的内容繁多,但是各集合之间具有很大的共通性。所以就动了写博客的念头。
    在安卓开发的时候已经有在用集合了,具体是用ArrayList向上转型到list对象。

    我觉得集合比数组方便的地方主要有4个:

  • 所有操作都是基于对象进行,符合java的核心思想。
  • 不用担心数据项的增加导致的数组溢出的情况。
  • 在插入、删除等等操作的时间开销较少。
  • Map接口的子接口以及实现类可以存放具有映射关系的数据。

    缺点也不是没有,可能是我学的不够深,暂时只发现了一个:Collection接口的子接口以及实现类大部分都是基于一个长度为16的数组实现,所以当插入的数据项少于16时可能会造成资源的浪费。

    java集合主要由两个接口派生而来:Collection以及Map。

    下面是两个接口的概述图

    图的来源为李刚老师的《疯狂java讲义》,如有侵权请联系删除。

    其中Collection接口的Vector实现类是不建议使用的,一是年代有点久远,二是已经有更先进更好用的ArrayList可以替换使用。

    下面是Collection、Map接口以及各实现类、子接口的用法(持续更新)。

    Collection接口

    Iterator接口

    本文首发于cartoon的博客

    转载请注明出处:https://cartoonyu.github.io/cartoon-blog

    近段时间有一个需求:在线获取图片并且显示在界面上。因为在线获取图片必定会有延迟,如果在主线程中获取会有很大几率造成主线程阻塞。解决的办法是开辟子线程进行网络访问。新的问题又出现了:android的UI更新必须在主线程中完成。但是子线程的值脱离线程会无效,造成java.lang.NullPointerException。所以思考了一下决定用android自带的异步处理机制:Handler,进行消息的回调。

  1. 线程的开辟。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void downloadImage() {
new Thread(new Runnable() {
@Override
public void run() {
final Bitmap bitmap= ServerImage.downloadFile(); //在线获取图片
Looper.prepare();
Message message=new Message();
message.what=0;
message.obj=bitmap;
handler.sendMessage(message);
Looper.loop();
}
}).start();

}
  1. 自定义Handler。
1
2
3
4
5
6
7
8
9
10
11
class ImageHandler extends Handler{
@Override
public void handleMessage(Message msg){
//编写自定义逻辑
switch (msg.what){
case 0:{

}
}
}
}

         其中switch中的case与调用handler时定义的msg.what要严格一致。

  1. handler对象的定义

     定义的时候注意一点:要在子线程外定义。

     我尝试过在子线程内定义,结果在把handler里面得到的图片赋值给UI组件时发生java.lang.NullPointerException。不清楚什么原因,但是确实挺有趣的,有时间会探求一下里面的原理。

    本文首发于cartoon的博客

    转载请注明出处:https://cartoonyu.github.io/cartoon-blog

    近些时间在开始学MySQL,安装挺顺利的,按照网上现成的教程就能安装成功。
    但是,在输入

1
mysql -uroot -p

    再输入密码时,遇到了这个情况

1
Access denied for user 'root'@'localhost' (using password: YES)

    在网上找了很多解决办法,但是基本只有一个,在.ini文件中的mysqld条目添加

1
skip-grant-tables

    然后重启服务器,再按照刚刚的步骤再来一遍(最后不输入密码),但是还是一条语句把我拦了下来

1
Access denied for user 'root'@'localhost' (using password: NO)

    综合了网上很多方法,自己一个一个拼接着去试,最后成功了
    总体上的思想还是修改.ini配置文件的内容,不过是通过命令行的形式修改,不知道是不是因为版本迭代了把以前那个直接修改文件的方法屏蔽了,无论如何,通过命令行修改在MySQL 8.0上是可以的。

    下面开始吧。

  • 以管理员身份打开cmd,切换到MySQL的bin目录
  • 关闭MySQL服务器
1
net stop mysql
  • 跳过输入密码的步骤(注意:文件名字与路径要与自己的吻合)
1
mysqld --defaults-file="D:\MySQL\my.ini" --console --skip-grant-tables
  • 如果出现类似截图圈起来的语句则说明成功

  • 重启服务器

1
net start mysql
  • 登录MySQL服务器
1
mysql -uroot -p
输入密码之后就能登录成功了。(数字1跟字母l很像很像)
  • 到这一步差不多就能完成了,但是当我输入
1
show databases;

    MySQL给我的反馈是:

1
You must reset your password using ALTER USER statement before executing this statement.

    我的猜测应该是MySQL认为安装时提供的随机密码不安全,让用户重置密码。
    网上找了一下,然后找到的现成办法
    参考文章:https://dev.mysql.com/doc/ref...

  • 密码永不过期的

    1
    ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码' PASSWORD EXPIRE NEVER;
  • 密码有限期的

    1
    ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码' PASSWORD EXPIRE;

         然后重新登录一下服务器就能正常的操作了。

    本文首发于cartoon的博客

    转载请注明出处:https://cartoonyu.github.io/cartoon-blog

    这是我的第一篇博文,请大家多多指教!

    大概一个月之前,在跟朋友合作开发一个APP的过程中,我们发现到一个问题:图片的存储。因为数据库没有图片这种数据类型,当用户上传的图片需要存储的时候,我们无法将其直接放进数据库中。

    在经历了几天的探索,结合郭神的《第二行代码》调用摄像头拍照以及从相册中选择图片这两小节,我们发现了Android里面的一个图片类:Bitmap。最终发现,利用Bitmap及其相关的工具类即可实现图片的存储以及显示。

    主要用到的工具类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;

import java.io.ByteArrayOutputStream;

/**
* Created by cartoon on 2017/12/9.
*/

public class StringAndBitmap {
//图片与String之间的转换,便于将图片存储在数据库中
private Bitmap bitmap;
private String string;
public Bitmap stringToBitmap(String string){
//数据库中的String类型转换成Bitmap
if(string!=null){
byte[] bytes= Base64.decode(string,Base64.DEFAULT);
bitmap= BitmapFactory.decodeByteArray(bytes,0,bytes.length);
return bitmap;
}
else {
return null;
}
}
public String bitmapToString(Bitmap bitmap){
//用户在活动中上传的图片转换成String进行存储
if(bitmap!=null){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] bytes = stream.toByteArray();// 转为byte数组
string=Base64.encodeToString(bytes,Base64.DEFAULT);
return string;
}
else{
return "";
}
}
}

    下面已经获取到数据库中已经存储了的图片的String语句string,只需要在需要显示图片的组件中调用关于显示Bitmap的方法即可。

1
2
imageView.setImageBitmap(stringAndBitmap.stringToBitmap(string);
//这里的imageView为页面组件绑定的ID,string为从数据库获取到图片的string形态

    而存储用户上传的图片则需要这样即可。

1
2
3
bitmap=((BitmapDrawable)imageView.getDrawable()).getBitmap();
string=stringAndBitmap.bitmapToString(bitmap);

    经过一些数据库的操作,即可以把用户上传的图片存入到数据库中。

    因为数据库部分不是我负责的,所以我的建议是数据库中的类型选择BLOB(MySQL),因为已经实现过是可行的。

     以上就是之前开发的一点小技巧,也是经过痛才领会出来的。我们还没有测试过资源的消耗以及延时的情况,但确实是可以存储图片到数据库中的。

    如果你们有任何对这篇博文的建议或者意见的话,欢迎私信或者在下方评论。最重要的是可以帮助到像我们一样的入门者。