JAVA 笔记(九)
- Iterator类中的next()是获取元素,并移动到下一个位置。[所以使用要小心,不要随便用,因为每次使用都是访问一个对象]返回类型是object真正是E(泛型)hasNext()如果仍有元素可以迭代就返回ture.
- 迭代器是依赖集合而存在的,否则没有意义。
- 集合的使用步骤;1.创建集合对象2.创建元素对象3.将元素添加到集合4.遍历集合(通过集合对象获取迭代器对象,再通过hasnext()和next()方法)
- 迭代器具体的实现类是真正的具体的子类中,以内部类的方式实现的。【这些集合相关的一般在util包中】。
- List(arraylist 、vector、linkedlist)集合是可以重复的并且是有序的(这里的有序是指如何顺序进就以如何顺序出,因为这样,就好像有了索引)而set(hashset,treeset)是不能有重复的元素。
- List集合特有的方法:可以在指定的位置添加元素(可以紧跟这一位,多了就会出现异常)。Set()修改元素【根据索引修改元素,返回被修改的元素】。
- List集合的特有遍历可以通过size()和get()方法完成。
- ListIterator(列表迭代器)继承了iterator,所以可以直接使用haxnext()和next()方法,进行遍历。它的特有功能可以逆向遍历(previous() 获取元素和hasprevious()判断是否有元素),但是该逆向遍历之前必须要进行正向遍历,否则没有意义(因为指针还是在起始处,没有动)
- 迭代器是依赖集合而存在的,集合中添加了数据,而迭代器却不知道,所以报错(并发修改异常)其实就是迭代器遍历元素的时候,通过集合是不能修改元素的。解决办法:A;迭代器迭代元素,迭代器修改元素【Listiterator】【该方法元素实在刚才迭代的元素后面的】。B;集合遍历元素,集合修改元素。(通过for循环)【该方法元素是最后添加的】
- 数组:查询快(通过索引)但是增加和删除复杂。链表:由一个链子把多个结点连接起来组成的数据(结点:有数据和地址组成(数据域和指针域,指针域里面是下一个元素的地址))。
- 链表查寻较慢,但是增加删除块。
- List的三个字类:arraylist(底层数据结构是数组,查询快,增删慢,线程不安全,效率高【异步】)vector:底层数据结构是数组,查询快,增删慢,线程安全,效率低(现在很少用了,有替代的类)linkedlist:底层数据结构是链表,查寻慢,增删快,线程不安全,效率高)。
- Vector的特有功能:addelements()添加功能 elementat():获取元素的位置,elements()遍历。不过这些方法都被后来的替代了,很少用,了解即可。
- Linkedlist的addlast()方法和add()一样,没有什么特别之处,所以很少用。
- Contains()方法底层依赖equals()方法,所以比较内容的时候要重写equals()方法,否则默认调用父类object中的equals()方法,那么比较的就是地址值了。
- 集合添加的都是引用类型,我们有时看到的的是基本类型,其实是自动装箱了(valueof()方法可以将基本类型装换为包装类型)。
- 集合也模拟数组的的做法,在创建对象的时候明确元素的数据类型,这种技术就叫泛型技术。
- 泛型:是一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。【参数化类型】把类型当做参数一样传递。格式<数据类型>[这里的数据类型指的是引用类型]
- 泛型的好处:A;把运行期间的问题提前到了编译期间B;避免了强制类型转换C;优化了程序设计,避免了黄色警告。
- 早期的时候,我们用object类来代表任意类型,向上转型是没有问题的,但是向下就隐含了类型转换问题,所以并不安全,在jdk5之后就提出了泛型【提高程序的安全性】。
- 泛型定义在类中public class 类名<泛型类型,…..> 泛型定义在方法中public <泛型类型>返回类型 方法名<泛型类型> 【传什么就是什么类型】泛型定义在接口中:public interface 接口<泛型类型1,……>
- 泛型如果明确写的时候,等号两边的类型必须一致。
- 泛型高级:1.?:表示任意类型,如果没有明确,就是object类以及任意的java类。2.?extends E:向下限定,【E及其子类】3.? Super E:向上限定【E及其父类】。
- Jdk5的新特性:自动拆装箱,泛型,增强for,静态导入,可变参数,枚举。
- 增强for的格式for(元素数据类型 变量:数组或者集合){输出变量即可,变量就是元素。}
- 增强for的目标不能是null,否则会出错,所以使用增强for之前要判断是否为null.判断之后在使用。
- 其实增强for就是代替迭代器的。
- 静态导入:import static 包名…类名.方法名【直接导入到方法的级别】注意事项:方法必须是静态的,如果方法名称相同,要加前缀(这些东西很少用,了解即可)
- 可变参数的格式 修饰符 返回值类型 方法名(数据类型…变量名){}。注意:这里的变量底层其实是一个数组。如果一个方法有多个参数,可变参数一定是最后一个。
- Public static <t>List<t>asList(t…a)将数组变成一个集合,但是注意:虽然可以把数组变成集合,但是该集合的长度不可改变。所以添加和移除没用,但是修改可以。
- 去重代码(下面这个较为麻烦,很少使用,但是要了解它)
import java.util.ArrayList; public class Demo { public static void main(String[] args) { ArrayList<String> list = new ArrayList<String>(); list.add("hello");list.add("world");list.add("java"); list.add("world");list.add("world");list.add("world");list.add("world"); list.add("java");list.add("hello");list.add("world");list.add("java");list.add("world"); for (int x = 0; x < list.size() - 1; x++) { for (int y = x + 1; y < list.size(); y++) { if (list.get(x).equals(list.get(y))) { list.remove(y); y--;// 这个地方要注意,如果元素相连并且相同,那么上一步虽然移除,但是下一个任然相同,这样就有漏网的,为了解决这个问题,让其减一,重新来一次就好了。 } } } for (String s : list) { System.out.println(s); } } }
用Linkedlist模拟栈的数据结构的集合,这个封装的思想非常好,要学会其精髓。【虽然这样很少用,但是其思想很优秀】
package hhxu.lianxi; import java.util.LinkedList; public class UtilTest { private LinkedList link; public UtilTest() { link=new LinkedList();//创建UtilTest对象的时候,其实是linkedlsit创建对象 } public void add(Object obj){//增加 link.addFirst(obj);//方法体中调用的是linkedlist方法 } public Object get(){//取出 return link.removeFirst(); } public boolean isEmpty(){//判断是否为空 return link.isEmpty(); } } package hhxu.lianxi; public class TestStack { public static void main(String[] args) { UtilTest ut=new UtilTest(); ut.add("hello"); ut.add("world"); ut.add("java"); while(!ut.isEmpty()){ System.out.println(ut.get()); } } }
- 包的划分原则:A;按功能分B;按模块分C;先按照模块分,再按照功能分。
- 记住一个原则:当参数较少时,就写参数传递,当参数较多时,就传一个对象。
- 多个对象共享一个成员变量的时候,要用静态的
- 循环里面如果有switch,并且在switch里面有break,那么结束的不是循环,而是switch语句。
- 不让别人创建对象就写构造方法为private 类名(){}。然后讲方法写成静态的即可。
- Set集合不能有重复的元素并且无序(存储顺序和取出顺序不一致)。注意;set集合虽然是无序的,但是作为集合它肯定有自己的存储顺序,假如你的顺序恰好跟其一样,属于巧合,不能代表其有序,多加几个数据就会发现结果。
- hashset为什么存储字符串的时候,字符串内容相同的只能存储一个?通过查看add方法的源码可知,其实这个方法的底层依赖hashcode()和equals()这两个方法:步骤:首先比较哈希值,如果相同,继续比较地址值或者equals(),如果不同接直接添加到集合中。按照方法的步骤来说:先看hashcode()的值是否相同,相同就比较equals()方法,返回ture,说明元素重复,就不添加,反之就添加。不同就直接添加。如果类没有重写这两个方法,默认就是object类中的,一般来说不相同,而string类重写了这两个方法,所以对于相同的元素只保留一个。【延伸:这样说明了一个问题,如果hashset集合出现了同样的元素的解决方法就是重写父类object中的hashcode()和equals()方法】。
- 不同元素的hashcode值一般不会相同,但是有时也会相同,这也是为什么比较hashcode()之后还要比较equls()的原因。-------->待续