带你轻松搞定Java面向对象的编程--数组,集合框架
作者:给我new一个亿
一、数组
1.数组的定义
数组是为了解决同类数据整合摆放而提出的,可以理解为一组具有相同类型的变量的集合,它的每个元素都具有相同的数据类型。
2.数组的声明
1.<data_type>[] <array_name>; 2.<data_type> <array_name>[];
例如定义保存学生成绩的语法:
1.float[] scores; 2.float scores[];
虽说两种写法都没错,但是按照Java语言的变成习惯,推荐各位采用第一种写法,即把中括号放在数据类型和变量名中间。
注意:
- 数组的类型实际上是指数组元素的取值类型。对于同一个数组,其所有元素的数据类型都是相同的。
- 项目数组名的书写规则应符合标识符的书写规定。
- 数组名不能与其他变量名相同。
- 在数组声明中包含数组长度永远是不合法的,如float[] scores;。因为,声明的时候并没有实例化任何对象(没有分配空间),只有在实例化对象时,JVM才分配空间,这时才与长度有关。
3.数组的初始化
数组有两种初始化
- 静态初始化
静态初始化的方式是在声明数组变量的同时进行的。这种方式不仅定义了数组中包含的元素的数量,而且制定了每个元素的值。
注意,静态初始化应该在一条语句内完成,不能分开写。
例如:
float[] scores = {93.5f,83,61,80}; int[] arr ={1,2,3,4,5};
- 动态初始化
动态初始化的方式是在声明数组时就必须定义数组的大小,以及每个元素的初始值。如果要定义的数组长度或数组数据只有在运行时才能决定,就要使用动态初始化。
注意,动态初始化时也可以使用变量的值来定义数组大小
例如:
int[] arr; arr = new int[10]; char[] c = new char[100]; int[] d = new int[]{1,2,3,4};
抽象类的使用原则如下:
(1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public;
(2)抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理;
(3)抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类;
(4)子类(如果不是抽象类)则必须覆写抽象类之中的全部抽象方法(如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。)
二、集合概述
在java.util包中提供了所有用到的集合类。
集合 简单来说就是存储对象的容器
集合中可存储任意类型的对象,最重要的是长度可变
不过集合类存放的都是对象的引用,而非对象本身,集合也不能存储基本数据类型
下图是集合框架:
三、Collection接口
1.Collection接口概述
Collection是单向集合。Set接口、List接口都是Collection接口的子接口
2.集合框架的三个组件
集合类主要有Set、List、Map
- Set(集):无序、不可重复
- List(列表):有序,可重复 常用的列表类有Vector、Stack、LinkedList、ArrayList
- Map(映射):保存的是键值对(key-value),映射中存储的每个对象(value)都有一个相关的关键字(key)对象。一个Map对象的每一个关键字应是惟一的(否则key可能对应多个value),就是说key-value是单向一对一的关系 常用的映射类有HashTable、HashMap、TreeMap
由于Set和List都是Collection的子接口,那么Set和List的所有实现类都实现了下面所示的Collection的方法
方法 | 摘要 |
---|---|
boolean add(E e) | 确保此集合包含指定的元素(可选操作) |
boolean addAll(Collection<? extends E> c) | 将指定集合中的所有元素添加到此集合(可选操作) |
void clear() | 从此集合中删除所有元素(可选操作) |
boolean contains(Object o) | 如果此集合包含指定的元素,则返回 true ) |
boolean containsAll(Collection<?> c) | 如果此集合包含指定 集合中的所有元素,则返回true |
boolean isEmpty() | 如果此集合不包含元素,则返回 true |
Iterator iterator() | 返回此集合中的元素的迭代器 |
boolean remove(Object o) | 从该集合中删除指定元素的单个实例(如果存在)(可选操作) |
Object[] toArray() | 返回一个包含此集合中所有元素的数组 |
T[] toArray(T[] a) | 返回包含此集合中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型 |
3.Iterator接口
所谓的“Collection是所有集合类的跟接口”,并不意味着Collection就是“根”。其实,Collection是Iterator接口的子接口,只不过Iterator(迭代器)不属于集合的范畴而已,那么Iterator接口作用是什么呢?
Iterator叫做“迭代器”,它允许访问一个容器(container)对象中的各个元素,而又不需要公开该对象的内部细节,从定义上看,迭代器为容器而生。由Collection接口继承了Iterator,所以所有集合对象都可以被迭代,Collection接口内定义了 iterator() 方法,能获得一个Iterator迭代器,从而实现对集合的迭代。
迭代器的用法:
Iterator it = Collection.iterator(); while(it.hasNext()){ Object obj = it.next(); }
Iterator如何对ArrayList进行迭代
public class IteratorDemo { public static void main(String[] args) { //创建List集合对象 List<String> alist = new ArrayList<String>(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); //设定迭代内容为String对象 Iterator<String> it = alist.iterator(); while(it.hasNext()){ //此时就可以直接使用String来接收返回值了 String s = it.next(); System.out.println(s); } } }
四、List接口
List继承了Collection,是有序的列表,该接口定义的元素是有序的且可重复的。在List接口下使用最多的就是ArryList实现类和LinkList实现类。
1.ArrayList类
ArrayList类是List接口的大小可变数组的实现(继承AbstractList,同时实现List接口)。
ArrayList是动态数组,所以保持了数组的特性。在ArrayList执行查询操作将非常快,但如果执行增加(特别是插入)、删除操作,效率低下。
ArrayList类的特点如下:
- 大小是可变的,是自动增长的,可动态的增加或减少元素,可存储null值
- 实现了ICollection 和 IList 接口
- 它是非同步的集合类
- 元素可以重复
构造方法
在这里我只写一种构造方法
ArrayList<Object> alist = new ArrayList<Object>;
ArrayList类的方法:
方法 | 摘要 |
---|---|
boolean add(E e) | 将指定的元素追加到此列表的末尾 |
void add(int index, E element) | 在此列表中的指定位置插入指定的元素。 |
boolean addAll(Collection<? extends E> c) | 按指定集合的Iterator返回的顺序将指定集合中的所有元素追加到此列表的末尾 |
boolean addAll(int index, Collection<? extends E> c) | 将指定集合中的所有元素插入到此列表中,从指定的位置开始 |
void clear() | 从此集合中删除所有元素 |
Object clone() | 返回此 ArrayList实例的浅拷贝 |
boolean contains(Object o) | 如果此集合包含指定的元素,则返回 true ) |
void ensureCapacity(int minCapacity) | 如果需要,增加此 ArrayList实例的容量,以确保它可以至少保存最小容量参数指定的元素数 |
void forEach(Consumer<? super E> action) | 对 Iterable的每个元素执行给定的操作,直到所有元素都被处理或动作引发异常 |
E get(int index) | 返回此列表中指定位置的元素 |
int indexOf(Object o) | 返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1 |
boolean isEmpty() | 如果此列表不包含元素,则返回 true |
E remove(int index) | 删除该列表中指定位置的元素 |
boolean remove(Object o) | 从列表中删除指定元素的第一个出现(如果存在) |
E set(int index, E element) | 用指定的元素替换此列表中指定位置的元素 |
int size() | 返回此列表中的元素数 |
List subList(int fromIndex, int toIndex) | 返回此列表中指定的 fromIndex (包括)和 toIndex之间的独占视图 |
Object[] toArray() | 以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组 |
T[] toArray(T[] a) | 以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型 |
2.LinkedList类
ArrayList类用于创建链表数据结构对象。与ArrayList一样,LinkedList也实现了List接口,这说明可根据索引来查询集合内的元素。
由于LinkedList实现了双向循环链表,所以可以很快捷地插入或删除元素;但由于链表的特性,如果对LinkedList执行查询,那么效率也非常低。可以说ArrayList和LinkedList是互补关系
构造方法
在这里我只写一种构造方法
LinkedList<Object> llist = new LinkedList<Object>;
LinkedList类的方法:
方法 | 摘要 |
---|---|
boolean add(E e) | 将指定的元素追加到此列表的末尾 |
void add(int index, E element) | 在此列表中的指定位置插入指定的元素 |
boolean addAll(Collection<? extends E> c) | 按照指定集合的迭代器返回的顺序将指定集合中的所有元素追加到此列表的末尾 |
boolean addAll(int index, Collection<? extends E> c) | 将指定集合中的所有元素插入到此列表中,从指定的位置开始 |
void addFirst(E e) | 在该列表开头插入指定的元素 |
void addLast(E e) | 将指定的元素追加到此列表的末尾 |
void clear() | 从列表中删除所有元素 |
boolean contains(Object o) | 如果此列表包含指定的元素,则返回 true |
E element() | 检索但不删除此列表的头(第一个元素) |
E get(int index) | 返回此列表中指定位置的元素 |
E getFirst() | 返回此列表中的第一个元素 |
E getLast() | 返回此列表中的最后一个元素 |
int indexOf(Object o) | 返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1 |
int lastIndexOf(Object o) | 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1 |
ListIterator listIterator(int index) | 从列表中的指定位置开始,返回此列表中元素的列表迭代器(按适当的顺序) |
E remove() | 检索并删除此列表的头(第一个元素) |
E remove(int index) | 删除该列表中指定位置的元素 |
boolean remove(Object o) | 从列表中删除指定元素的第一个出现(如果存在) |
E removeFirst() | 从此列表中删除并返回第一个元素 |
E removeLast() | 从此列表中删除并返回最后一个元素 |
E set(int index, E element) | 用指定的元素替换此列表中指定位置的元素 |
int size() | 返回此列表中的元素数 |
Object[] toArray() | 以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组 |
T[] toArray(T[] a) | 以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型 |
五、Set接口
Set接口 继承Collection接口。他存储的是无序的,惟一的集合元素
1.HashSet类
实现了Set接口,是基于HashMap实现,存储不重复,无序值
HashSet 是根据对象的哈希值来确定元素在集合中的存储位置,元素再插入时就确定了存储位置,因此,元素在集合中的存储位置时固定的(无序是指输出顺序 与存出顺序不一致),具有良好的存储和查询性能(存储速度快)。
构造方法
在这里我只写一种构造方法
Set ss = new HashSet();
HashSet 类常用的方法:
方法 | 摘要 |
---|---|
boolean add(E e) | 将指定的元素添加到此集合(如果尚未存在) |
boolean remove(Object o) | 如果存在,则从该集合中删除指定的元素 |
int size() | 返回此集合中的元素数(其基数) |
六、Map接口
Map接口 是一个根接口,他存储的是键-值对(key-value),其中key不允许重复,value允许重复。
1.HashMap类
HashMap类 实现了Map接口,存储的是无序的键-值对(key-value)。
- HashMap的key是用Set集合来存放,所以想做到key不允许重复,key对应的类需要重写hashCode()和equals()方法
- HashMap是线程不安全
- HashMap中的元素的位置是不定时的更新,即元素位置不固定
构造方法
在这里我只写一种构造方法
HashMap map = new HashMap();
HashMap 类常用的方法:
方法 | 摘要 |
---|---|
V put(K key, V value) | 将指定的值与此映射中的指定键相关联 |
V get(Object key) | 返回到指定键所映射的值,或 null如果此映射包含该键的映射 |
int size() | 返回此地图中键值映射的数量 |
V remove(Object key) | 从该地图中删除指定键的映射(如果存在) |
七、泛型
为什么要使用泛型程序设计?以常用的ArrayList类为例,在使用ArrayList的时候常遇到以下两个问题
- 当获取一个值的时候必须进行强制类型转换
- 当向其中放入值的时候没有任何约束,只要是对象就行。
这样,如果处理数据类型时稍微出现一点问题,程序就会报错!
泛型提供了一个解决方案:类型参数(type parameters)。如果ArrayList类有一个类型参数指示元素的类型,就没有问题了
ArrayList<String> arr = new ArrayList<String>();
这时程序员可以很方便的分辨其中元素的类型,编译器也可以很好的利用这个信息。所以当调用get()方法时,不需要执行类型转换,编译器就可以返回值类型为String。
String str = arr.get(0);
编译器还知道ArrayList < String> 中add()方法有一个类型为String的参数。这将比直接使用Object类型的参数安全。如果在尝试向其中放入非String的数据,编译器就会发出通知,以避免发生错误。
arr.add(new Integer(1));
总结
本篇文章的内容就到这了,希望大家可以喜欢,也希望大家可以多多关注脚本之家的其他精彩内容!