JavaSE学习笔记 Day18
个人整理非商业用途,欢迎探讨与指正!!
« 上一篇
文章目录
- JavaSE学习笔记 Day18
- ···
- 16.2.2迭代器
- 16.2.3泛型的基本使用
- 16.3常见的单列集合实现类
- 16.3.1ArrayList
- 16.3.2List集合的遍历
- 16.3.3ArrayList的底层实现
- 16.3.4LinkedList
- 16.3.5LinkedList底层实现
- 16.3.6Vector
- 16.3.7HashSet
- 16.3.8HashSet数值的存放
···
16.2.2迭代器
反复反馈的过程,通常就是为了获取结果使用的。迭代和遍历是类似的
每次迭代都是重复的过程,每次迭代的结果作为下一次的初始值
迭代器是传统的遍历方式,JDK1.5之前使用
迭代器的方法
hasNext:判断迭代器是否有下一个元素
next:获取当前游标对应的元素,将游标向后移动一位
remove:移除当前迭代器中的数据
public class Demo02 {public static void main(String[] args) {Collection coll = new ArrayList();coll.add("hello");coll.add(new Integer(10));coll.add(20);coll.add("bmh");// 可以通过集合获取迭代器
// 迭代器可以帮我们进行集合的遍历(JDK1.5之前)Iterator iterator = coll.iterator();// 判断当前是否有元素while(iterator.hasNext()) {
// 获取当前,向后移位System.out.println(iterator.next());}}
}
迭代器的常见问题:
1.迭代器是一个一次性的工具,迭代完成之后,游标会停到最后一位,就不能在向下了,迭代器空了没有数据了
2.迭代时每次循环不能调用多次next(),若想调用多次,数据是next()的倍数,否则抛出NoSuchElementException
3.迭代时不要向集合中添加或者删除元素,会抛出ConcurrentModificationException(并发修改异常)
public class Demo02 {public static void main(String[] args) {Collection coll = new ArrayList();coll.add("hello");coll.add(new Integer(10));coll.add(20);coll.add("bmh");coll.add("bmh");// 可以通过集合获取迭代器
// 迭代器可以帮我们进行集合的遍历(JDK1.5之前)Iterator iterator = coll.iterator();// 判断当前是否有元素/*while(iterator.hasNext()) {
// 获取当前,向后移位System.out.println(iterator.next());}*/System.out.println("------------------------");
// 第二次迭代/*while(iterator.hasNext()) {System.out.println(iterator.next());}*/System.out.println("------------------------");/*while(iterator.hasNext()) {
// 获取当前,向后移位System.out.println(iterator.next());System.out.println(iterator.next());System.out.println("=======");}*/System.out.println("------------------------");while(iterator.hasNext()) {
// 向集合中添加元素coll.add("hi");
// 获取当前,向后移位System.out.println(iterator.next());}}
}
16.2.3泛型的基本使用
Java中的菱形语法:<>
JDK1.5后引入
参数化类型,可以擦除数据类型,消除向下造型
集合都是泛型类或者泛型接口
public class Demo03 {public static void main(String[] args) {
// 泛型写Object及其任意的子类(基本类型不能写)
// 前后的类型需要一致,或者前写后不写,默认和前是一致的
// Collection<Integer> coll = new ArrayList<Integer>();
// 泛型添加之后,规范化了类型,如下:当前的集合中只能添加Integer类型Collection<Integer> coll = new ArrayList<>();
// 规定好了类型
// coll.add("hello");coll.add(10);coll.add(20);// 集合都是泛型类或者接口 Iterator迭代器也是集合Iterator<Integer> iterator = coll.iterator();while(iterator.hasNext()) {System.out.println(iterator.next());}Collection<String> coll1 = new ArrayList<>();coll1.add("helloworld");coll1.add(new String("你好世界"));Iterator<String> it = coll1.iterator();while(it.hasNext()) {System.out.println(it.next());}}
}
16.3常见的单列集合实现类
16.3.1ArrayList
List接口的实现类
底层使用数组完成
常用方法:
add(int index, E element) 向集合指定下标中添加元素
add(E e) 在集合的尾部添加元素
get(int index) 通过下标返回指定位置的元素
set(int index, E element) 设置修改,修改的指定下标的内容
listIterator() 获取list专属迭代器
subList(int fromIndex, int toIndex) 集合的截取,从fromIndex到toIndex(不包含)结束
public class Demo04 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();
// 添加list.add("张三");list.add("李四");list.add("王五");
// toString是重写过的System.out.println(list.toString());
// 在指定位置进行添加元素list.add(0, "赵六");System.out.println(list);
// 下标需要在范围之内
// list.add(-1,"小七");// list中可以添加null值list.add(null);System.out.println(list);
// 清空/*list.clear();System.out.println(list);*/// 返回下标System.out.println(list.indexOf("张三"));System.out.println(list.indexOf(null));// 是否包含System.out.println(list.contains("李四"));// 通过下标移除 返回结果为刚刚被删除的数据System.out.println(list.remove(0));System.out.println(list);// 修改集合的内容 返回的是原本的值System.out.println(list.set(0, "wch"));System.out.println(list);// 获取方法System.out.println(list.get(0));// 集合的截取List<String> subList = list.subList(0, 2);//返回值是List的一个实现类型中的内部类(继承了AbstractList的)System.out.println(subList);}
}
16.3.2List集合的遍历
有三种方式
1.迭代器
2.foreach循环
3.for循环(只能遍历list集合)
public class Demo05 {// list集合的遍历public static void main(String[] args) {ArrayList<String> list = new ArrayList<String>();list.add("张三");list.add("李四");list.add("王五");// 1.迭代器Iterator<String> it = list.iterator();while(it.hasNext()) {System.out.println(it.next());}ListIterator<String> it1 = list.listIterator();
// 向下:下面是否有内容while(it1.hasNext()) {System.out.println(it1.next());}System.out.println("+++++++++++++++++++++++++");
// 向上:上面是否有内容while(it1.hasPrevious()) {System.out.println(it1.previous());}System.out.println("-------------------------");
// 2.foreachfor (String string : list) {System.out.println(string);}System.out.println("-------------------------");
// 3.普通for循环for(int i = 0;i<list.size();i++) {System.out.println(list.get(i));}}
}
16.3.3ArrayList的底层实现
ArrayList的底层是数组实现的,所有它有一些数组的特征(下标)
数组结构的特点:1.查询快,2.增删慢
add(E e)方法:
1.若为一次添加元素,那么将底层的空数组进行扩容默认是10,默认的容器可以手动的指定(调用的ArrayList的带参构造)
2.若不为第一次添加元素,当有效个数为size+1,大于数组(底层默认的数组)的长度了就需要扩容
3.每次的扩容为原来的1.5倍(oldCapacity + (oldCapacity >> 1))
ps:移位运算符,是最快速的运算符
①a>>b 等价与 a / 2的b次方
②a<<b 等价与 a * 2的b次方
add(int index,E e)方法:
1.检测下标的范围是否合法
2.判断是否需要扩容
3.将原数组的index下标位向后拷贝
4.在index下标位添加新元素e
5.有效个数++
get(int index)方法:
1.判断下标是否合法
2.返回指定位置的元素
…
16.3.4LinkedList
api和ArrayList类似,有自己独特的添加首尾的方法
底层使用的双链表实现的
public class Demo06 {public static void main(String[] args) {LinkedList<String> list = new LinkedList<>();
// 方法 默认是添加到最后的list.add("张三");list.add("李四");list.add("王五");System.out.println(list);
// 添加到结尾list.addLast("赵六");System.out.println(list);
// 添加到头部list.addFirst("李二");System.out.println(list);
// 获取头和尾System.out.println(list.getFirst());System.out.println(list.getLast());
// 和ArrayList类似的方法System.out.println(list.get(3));}
}
可以模拟栈和队列的数据结构
栈:先进后出
队列:先进先出
public class Demo07 {public static void main(String[] args) {
// 模拟栈LinkedList<String> list = new LinkedList<>();
// 入栈:先进后出
// 调用addFirstlist.push("张三");//先进入的存在最后 list.push("李四");list.push("王五");list.push("赵六");System.out.println(list.get(0));System.out.println(list);
// 出栈:将数据移除list.pop();//赵六出栈list.pop();//王五出栈list.pop();//李四出栈list.pop();//张三出栈System.out.println(list);System.out.println("--------------------------------");
// 模拟队列
// 调用add(默认添加到尾部)list = new LinkedList<>();list.offer("张三");list.offer("李四");list.offer("王五");list.offer("赵六");System.out.println(list);
// 出列list.poll();//张三list.poll();//李四list.poll();//王五list.poll();//赵六System.out.println(list);}
}
16.3.5LinkedList底层实现
底层选用双链表结构
数据结构中存在表结构
顺序表:内存空间是连续的,数组,允许随机访问,尾插和尾删方便,优点:查询快;缺点:插入的效率低,删除效率低,长度固定(查快,删改慢)
单链表:内存不是连续的,可以随意的增删改,查询效率低,应用:HashSet,HashMap
单链表只能下一个
双链表:和单链表类似,内存不连续,查询效率比单链表快一倍,但查询效率仍然是低的,应用:LinkedList
双链表可以下一个,也可以上一个
//LinkedList双链表的源码
private static class Node<E> {E item;//当前元素Node<E> next;//下一个元素Node<E> prev;//上一个元素//构造方法Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}
}
16.3.6Vector
与ArrayList方法基本一样
底层同样使用的是数组
Vector是线程安全的,底层中只要有synchronized关键字就是线程安全的
线程安全都是效率低
创建时底层数据的默认长度为10
和ArrayList有一定的区别,默认长度是0,第一次添加数据时才会扩容到10
查询快,在不考虑线程安全时使用ArrayList,考虑时使用Vector
public class Demo08 {public static void main(String[] args) {Vector<String> v = new Vector<>();v.add("张三");v.add("李四");System.out.println(v);v.remove("张三");System.out.println(v);
// 通过下标移除v.remove(0);System.out.println(v);v.remove("");}
}
16.3.7HashSet
Set集合的主要实现类之一
特点:无序(插入无序),无下标,不可重复,只能添加一个null值
常用的方法和Collection接口中基本一致
public class Demo09 {public static void main(String[] args) {HashSet<String> set = new HashSet<>();set.add("张三");set.add("李四");set.add("王五");
// 取出顺序和添加顺序无关:无序System.out.println(set);
// 没有下标
// set.get(0);
// 不可重复set.add("张三");System.out.println(set);
// 可以添加null值,但是只能加入一个set.add(null);set.add(null);System.out.println(set);}
}
16.3.8HashSet数值的存放
无序:只是添加和set集合的存放是不一样的
在存储时内部是有一套自己的方案的,按照hash值进行存放的
public class Demo10 {public static void main(String[] args) {HashSet<String> set = new HashSet<>();
// 0~9的hash值是连续的
// 无序并不是杂乱无章的,只是添加和存储的顺序不一样set.add("1");set.add("7");set.add("2");set.add("3");set.add("4");set.add("8");set.add("0");set.add("5");set.add("9");set.add("6");System.out.println(set);}
}