按照集合框架的继承体系,咱们先从Collection中的List接口开始学习
List在Collection中充当着一个什么样的身份呢?——有序的 collection(也称为序列) java
实现这个接口的用户以对列表中每一个元素的插入位置进行精确地控制。用户能够根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。与 set 不一样,列表一般容许重复的元素。数据库
//添加功能 boolean add(E e)向集合中添加一个元素 //删除功能 void clear():移除集合中的全部元素 boolean remove(Object o):从集合中移除指定的元素 boolean removeAll(Collection<?> c):从集合中移除一个指定的集合元素(有一个就返回true) //获取功能 Iterator iterator():就是用来获取集合中每个元素。 //判断功能 boolean isEmpty():判断集合是否为空 boolean contains(Object o):判断集合中是否包含指定元素 boolean containsAll(Collection<?> c):判断集合中是否包含指定的一个集合中的元素 //长度功能 int size():获取集合中元素的个数 //集合转换为数组 Object[] toArray()
//添加功能:在指定位置添加元素 void add(int index,Object element) //获取功能:获取指定位置的元素 Object get(int index) //列表迭代器:List集合特有的迭代器 ListIterator listIterator() //删除功能:根据索引删除元素,返回被删除的元素 Object remove(int index) //修改功能:根据索引修改元素,返回被修饰的元素。 Object set(int index,Object element)
咱们仍是先写一个List遍历字符串的代码数组
import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Demo1 { public static void main(String[] args) { //建立集合对象 List list = new ArrayList(); //存储元素 list.add("I"); list.add("love"); list.add("you"); list.add("❤"); list.add("❤"); //遍历集合 Iterator it = list.iterator(); while (it.hasNext()) { String s = (String) it.next(); System.out.print(s + " "); } } } //运行结果 I love you ❤ ❤
经过这段代码咱们能够看到,List集合的特色——有序(存储和去取出的元素一直),可重复安全
咱们再使用List存储学生对象并遍历看看网络
//Student 自行补充 //StudentDemo类 import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class StudentDemo { public static void main(String[] args) { List list = new ArrayList(); Student s1 = new Student("张三", 20); Student s2 = new Student("李四", 30); Student s3 = new Student("王五", 40); list.add(s1); list.add(s2); list.add(s3); Iterator it = list.iterator(); while (it.hasNext()) { Student s = (Student) it.next(); System.out.println(s.getName() + "---" + s.getAge()); } } } //运行结果 张三---20 李四---30 王五---40 //Student s = (Student)it.next(); //it.next()返回的是Object类型。 //(Student)it.next();是将Object类型强制转换成Student类型。 //这样才可以调用getName()方法和getAge()方法。
package cn.bwh_02_List.ArrayList; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class StudentDemo { public static void main(String[] args) { List list = new ArrayList(); Student s1 = new Student("张三", 20); Student s2 = new Student("李四", 30); Student s3 = new Student("王五", 40); list.add(s1); list.add(s2); list.add(s3); //迭代器遍历 Iterator it = list.iterator(); while (it.hasNext()) { Student s = (Student) it.next(); System.out.println(s.getName() + "---" + s.getAge()); } //利用List的功能遍历 for (int x = 0; x < list.size(); x++){ Student s = (Student) list.get(x); System.out.println(s.getName() + "---" + s.getAge()); } } }
上面几个实例中,咱们使用了Iterator迭代器遍历,下面咱们介绍一种特别的迭代器数据结构
ListIterator listIterator():列表迭代器:List集合特有的迭代器并发
列表迭代器继承于Iterator迭代器,能够直接使用hasNext() 和next()方法框架
基本功能:dom
//将指定的元素插入列表(可选操做) void add(E e) //返回 true若是遍历正向列表,列表迭代器有多个元素 boolean hasNext() //返回列表中的下一个元素,而且前进光标位置 E next() //从列表中删除由 next()或 previous()返回的最后一个元素(可选操做) void remove() //用 指定的元素替换由 next()或 previous()返回的最后一个元素(可选操做) void set(E e)
特有功能:ide
//获取上一个元素 Object previous() //判断是否有元素 boolean hasPrevious()
列表迭代器的好处是相比Iterator提供了更多的方法,而且能够实现正向遍历,才能逆向遍历,因此通常来讲意义不大。
import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; public class Demo1 { public static void main(String[] args) { //建立集合对象 List list = new ArrayList(); //存储元素 list.add("I"); list.add("love"); list.add("you"); list.add("❤"); list.add("❤"); ListIterator lit= list.listIterator(); //正向遍历 while(lit.hasNext()){ String s = (String)lit.next(); System.out.print(s + " "); } System.out.println(); //逆向遍历 while (lit.hasPrevious()) { String s = (String) lit.previous(); System.out.print(s + " "); } } } //运行结果 I love you ❤ ❤ ❤ ❤ you love I
我建立了一个集合,而且遍历它,使用if语句判断 是否集合中存在"love"这个字符串,若存在,就增长一个"❤"元素,咱们先顺着这个思路写一下代码:
import java.util.ArrayList; import java.util.Iterator; import java.util.List; /* * 并发修改异常 */ public class Demo2 { public static void main(String[] args) { //建立集合对象 List list = new ArrayList(); //存储元素 list.add("I"); list.add("love"); list.add("you"); Iterator it = list.iterator(); while (it.hasNext()) { String s = (String) it.next(); if ("love".equals(s)) { list.add("❤"); } System.out.println(s); } } } //运行结果(节选) Exception in thread "main" java.util.ConcurrentModificationException
咱们贴出JDK中对这个异常的解释:
This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.当不容许这样的修改时,能够经过检测到对象的并发修改的方法来抛出此异常。
当咱们对集合进行遍历的时候,咱们会获取当前集合的迭代对象
//List为例,获取集合的迭代对象 Iterator it = list.iterator();
这个迭代对象中,封装了迭代器的方法与集合自己的一些方法,当咱们在迭代中使用集合自己的add方法的时候,就产生了ConcurrentModificationException异常,通俗的说就是,在判断成功后,集合中元素增长了,可是迭代器不清楚,因此就报错,若是迭代器中含有这一种方法(假设),咱们是用迭代器添加元素就不会有问题了。
针对这个问题,咱们给出两个解决方案
##### 方式1:迭代器迭代元素,迭代器修改元素
咱们假想若是Iterator迭代器中有添加功能就行了,但很遗憾并无,可是它的子接口ListIterator却拥有这个功能
import java.util.ArrayList; import java.util.List; import java.util.ListIterator; public class Demo2 { public static void main(String[] args) { //建立集合对象 List list = new ArrayList(); //存储元素 list.add("I"); list.add("love"); list.add("you"); ListIterator lit = list.listIterator(); while (lit.hasNext()) { String s = (String) lit.next(); if ("love".equals(s)) { lit.add("❤"); } System.out.print(s + " "); } } } //运行结果 I love you
import java.util.ArrayList; import java.util.List; import java.util.ListIterator; public class Demo2 { public static void main(String[] args) { //建立集合对象 List list = new ArrayList(); //存储元素 list.add("I"); list.add("love"); list.add("you"); for (int x = 0; x < list.size(); x++){ String s = (String)list.get(x); if ("love".equals(s)){ list.add("❤"); } System.out.print(s + " "); } } } //运行结果 I love you ❤
二者都可以解决并发修改异常的问题,可是经过运行结果也能够看出,方法一添加后,在本次遍历中不会输出添加的结果,而方法二却能够。
补充:加强for循环实现将集合进行遍历,也产生了并发修改异常,这是由于加强for在底层也是调用的集合自己的remove
在迭代器遍历时,若是须要对集合进行增删操做时,要调用迭代器自己的remove方法,或者选择使用普通for进行遍历
特有功能 a:添加 public void addElement(E obj) -- add() b:获取 public E elementAt(int index) -- get() public Enumeration<E> elements() -- iterator()
下面的案例题目个别来源于网络,咱们来整理,书写一下。
需求:
咱们班有学生,每个学生是否是一个对象。因此咱们可使用一个集合表示咱们班级的学生。ArrayList<Student>
可是呢,咱们旁边是否是还有班级,每一个班级是否是也是一个 ArrayList<Student>
而我如今有多个ArrayList<Student>。也要用集合存储,怎么办呢 ?
按照咱们的想法就是这个样子的:ArrayList<ArrayList<Student>>
package cn.bwh_02_List.ArrayList.RandomDemo; import java.util.ArrayList; import java.util.Random; /* * 分析: * A:建立产生随机数的对象 * B:建立一个存储随机数的集合 * C:定义一个统计变量,从0开始 * D:判断统计遍历是否小于10 * 小于10: * 若不存在:就添加,同时统计变量++ * 若不存在:则不做处理 * 大于10; * 不做处理 * E:遍历集合 */ public class ArrayDemo { public static void main(String[] args) { Random r = new Random(); ArrayList<Integer> a = new ArrayList<Integer>(); int count = 0; while (count < 10) { int number = r.nextInt(20) + 1; if (!a.contains(number)){ a.add(number); count++; } } for (Integer i : a){ System.out.print(i + " "); } } }
键盘录入多个数据,以0结束,要求在控制台输出这多个数据中的最值
package cn.bwh_02_List.ArrayList.InputMore; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; /* * 分析: * A:建立键盘录入数据对象 * B:键盘录入多个数据,不知道数量,因此用集合存储 * C:以0结束——只要键盘录入的数据是0,就不继续录入数据了 * D:把集合转成数组 * E:对数组排序 * F:获取该数组中的最大索引的值 */ public class AeeayDemo { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入数据"); ArrayList<Integer> a = new ArrayList<Integer>(); while (true) { int number = sc.nextInt(); if (number != 0) { a.add(number); } else { break; } } Integer[] i = new Integer[a.size()]; a.toArray(i); Arrays.sort(i); System.out.println(i[i.length - 1]); } }
package cn.bwh.pojo; /** * 这是用户基本描述类 * * @author BWH_Steven * @version v1.0 */ public class User { private String username; private String password; public User() { } public User(String username, String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
package cn.bwh.dao; import cn.bwh.pojo.User; /** * 这是针对用户进行操做的接口 * * @author BWH_Steven * @version v1.0 */ public interface UserDao { /** * 这是用户登陆功能 * * @param username 用户名 * @param password 密码 * @return 返回登陆是否成功 */ public abstract boolean isLogin(String username, String password); /** * 这是用户注册功能 * * @param user 要注册的用户信息 */ public abstract void regist(User user); }
由于注册的时候极可能还要填写
例如地址,性别,爱好等等信息(而登陆功能的时候每每只须要用户名和密码),因此这个注册功能传进来的参数过多,所以用对象代替过多的参数,也就是说,经过传递对象(User user)包含众多信息避免了直接传递String username,password等等变量过多的问题
package cn.bwh.dao.impl; import cn.bwh.dao.UserDao; import cn.bwh.pojo.User; import java.util.ArrayList; /** * 这是用户操做的具体实现类(集合类) * * @author BWH_Steven * @version v1.0 */ public class UserDaoImpl implements UserDao { //为了多个集合可以使用同一个集合,就把集合定义为成员变量 //为了避免让外人看到,用private private static ArrayList<User> array = new ArrayList<User>(); @Override public boolean isLogin(String username, String password) { //遍历集合,获取每个用户,而且判断用户的用户名和密码是否和传递过来的匹配 boolean flag = false; for (User u : array) { if (u.getUsername().equals(username) && u.getPassword().equals(password)) ; flag = true; break; } return flag; } @Override public void regist(User user) { //把用户信息存入集合内 array.add(user); } }
package cn.bwh.test; import cn.bwh.dao.UserDao; import cn.bwh.dao.impl.UserDaoImpl; import cn.bwh.pojo.User; import java.util.Scanner; /** * 用户测试类 * * @author BWH_Steven * @version v1.0 */ public class UserTest { public static void main(String[] args) { //为了可以到主界面 while (true) { System.out.println("------------初次见面,请多指教------------"); System.out.println("1 登陆"); System.out.println("2 注册"); System.out.println("3 退出"); System.out.println("请输入你的选择"); Scanner sc = new Scanner(System.in); //为了后面录入信息方便,全部的数据录入均使用字符串接受 //Switch语句的多个地方要使用,对象就定义到外面 String choicString = sc.nextLine(); //调用注册功能,使用多态 UserDao ud = new UserDaoImpl(); switch (choicString) { case "1": System.out.println("----------------登陆系统----------------"); System.out.println("请输入用户名"); String username = sc.nextLine(); System.out.println("请输入密码"); String password = sc.nextLine(); //调用登陆功能 boolean flag = ud.isLogin(username, password); if (flag) { System.out.println("登录成功"); System.exit(0); //break; 这里break结束的是switch } else { System.out.println("用户名或者密码错误,登陆失败"); } break; case "2": System.out.println("--------------新用户注册---------------"); System.out.println("请输入用户名"); String newUsername = sc.nextLine(); System.out.println("请输入密码"); String newPassword = sc.nextLine(); //把用户名和密码封装到一个类中 User user = new User(); user.setUsername(newUsername); user.setPassword(newPassword); ud.regist(user); System.out.println("注册成功"); break; case "3": default: System.out.println("谢谢使用,感谢你曾经来过过"); System.exit(0); break; } } } }
dao层主要链接数据库,封装增删改查的数据库语句
daoimpl是实现dao层方法的接口,因此能够把具体实现的方法写在daoimpl中,dao层只写方法名就能够。
Pojo表明简单的Java对象
ArrayList:
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。
Vector:
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。
LinkedList:
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。
使用具体状况:
保证安全:Vector
(即便要安全,也不用这个,后面有替代的)
不保证安全:ArrayList或者LinkedList
查询多:ArrayList
增删多:LinkedList
若是内容中有什么不足,或者错误的地方,欢迎你们给我留言提出意见, 蟹蟹你们 !^_^
若是能帮到你的话,那就来关注我吧!(系列文章均会在公众号第一时间更新)
在这里的咱们素不相识,却都在为了本身的梦而努力 ❤一个坚持推送原创Java技术的公众号:理想二旬不止