对象的容纳
文章目录
基本数据类型数组初始化
动态初始化
int a[]=new int[100];
静态初始化
int a[]={21,34,7,8,10}
对于二维数组
double b[][]=new double[2][];
for(int i=0;i<b.lenth;i++){
b[i]=new double[i+1];
}
使用Arrays类对基础数据类型数组进行操作
方法 | 使用操作 |
---|---|
copyOf();//复制数组 | int b[]=Arrays.copyOf(a,a.lenth); |
equals();//判断两个数组是否相等 | equals(a,b); |
sort();//对数组进行排序 | sort(a,b); |
对象初始化
对象数组容纳的是对象的引用,而基本数据类型数组容纳的是具体的数值,所以对象还需要对每个引用再分配,不然值会是null
Appla a[]=new Apple[]{new Apple(),new Apple()};
对象的比较
Comparable接口
使用 [^ int compareTo(Object o)]方法,该接口只有这一个方法,对象o是被比较对象。大于、等于或小于指定对象o,分别返回正整数、零或复数(需要自己实现),不好直接用于排序。
public class Test{
public static void main(String args[]){
Integer x = 5;
System.out.println(x.compareTo(3));
}
输出结果
1
Comparator接口
拥有一个[^ compare(Object 1,Object2)]方法,当对象o1大于、等于或者小于对象o2时,分别返回正整数、0或负整数(需要自己是实现),实现了算法和数据的分离。
以下是一个降序比较器的实现
class D implements Comparator{
public int compare(Object o1,Object o2){
Comparable c1 = (Comparable)o1;
return 0-c1.compareTo(o2);
}
}
用通过Comparator接口实现的比较器,进行排序
Employee xl[]= {new Employee(2),new Employee(1),new Employee(5),new Employee(3),new Employee(4)};
Arrays.sort(xl,new D());
Arrays.sort()这个方法的形式
Arrays.sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c)
可以看出,使用Comparator接口实现的比较器,不需要关注是哪个对象,不局限于一个类。
枚举类型
所有枚举类型都是Enum类的子类,自然继承了它的一些方法,比较常用的有toString()方法和values()方法,第一个可以返回枚举的常量名,比如Season.SPRING,使用toString()返回字符串“SPRING”。values()方法返回一个包含所有枚举值的数组。
Season[] seasons = Season.values()
public enum Color {
RED, GREEN, BLANK, YELLOW
}
在使用的时候可以Color.RED
也可以加入变量和方法,也可以使用接口
public enum Color {
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
} }
- 枚举类型只能保存此类声明给定时的某个枚举值,或者null值。
容器
Java提供了“容器”机制,值得一提的是,这里的容器只能保存对象而 不能保存基本类型
几个强大的通用容器:List(列表)、Set(集合)、Map(映射),其中List和Set在类集(Collection)接口上得以实现,而
Collection接口从Iterable接口继承,代表所有实现Collection接口以及Collection子接口的类都可以使用迭代器。
List容器
List是 有序 的Collection。
动态数组:ArrayList线性表
是容量大小可变的数组
构造方法
方法 | 描述 |
---|---|
ArrayList() | 构造一个空的线性表 |
ArrayList(Collection) | 根据已有类集构造线性表 |
ArrayList(int) | 构造指定初始容量大小的线性表 |
缺点
ArrayList不利于查找,因为频繁地调用indexOf():获取指定元素位置、contains():查看是否有此元素这类方法会导致效率低下。
LinkedList链表
实现了链表这样的数据结构,插入删除的代价比较低,但是无法根据索引提供快速随机存取,内部维护的是双向链表。
最好先使用ArrayList,如果发现大量的插入和删除操作造成了性能的降低,再考虑换成LinkedList。
First代表链头,Last代表链尾,LinkedList在List上的基础上增加了如下方法
方法 | 描述 |
---|---|
addFirst() | 向链表头插入元素 |
getFirst() | 获取链表头元素 |
removeFirst() | 移除链表头元素 |
- 只需要把First换成Last就是对链表尾进行操作
set容器
实现的是集合这种数据结构,和List不同,它不能保存相同值得元素,也没有顺序的概念
HashSet散列集
set容器不允许再存储值一样的元素,但是要避免这种情况,需要查找是否有相同元素,这是耗时的,所以使用散列集来解决这一问题,它使用了一种快速查找特定对象的数据结构,也就是散列表,它会计算散列码(hashcode)来进行插入和查找。
构造方法
HashSet()的构造函数里可以为空,这时候容量为16,载入因子为0.75,也可以是collection,即从其他类集中构造,也可以是(int,float),这样可以指定初始容量和载入因子。
- 散列集实现后,如果存储了相同值得元素因子,也只会保存一个,也不会报错,但是add中返回为false。
容量因子
Java默认得容量因子是2的幂,初始为16,载入因子默认0.75,也就是16条链表中的百分之七十五链接有数据的时候,HastSet将会重新开始散列,重新开一个散列单元大小为32的散列结构,因此我们需要设计合适的容量。
散列集add()调用方法
add()会先调用hashCode()(可重载),然后再调用equals()(可重载)比较是否有相同元素。
方法 | 描述 |
---|---|
int hashCode() | 计算散列值,并返回 |
boolean equals(Object o) | 和o进行比较,然后相同返回true,不同则返回false |
其他集合
- TreeSet(红黑树)
- LinkedHashSet(是HashSet的子类,在其基础上将每一个元素用链表串连起来,与其他集合不同的是,它会保持添加顺序)
Map(映射)
实现了一个映射结构,维护了键(Key)-值(Value)的无序容器。其中每个键映射到一个值,可以通过一个键找到响应的值,键和值都视为对象。
构造方法
Map<Integer,String>map=new HashMap<Integer,String>();
一些方法
方法 | 描述 |
---|---|
put(K,V) | 将指定的键和值相关联,如果此键已经存在,则替换值 |
get(Object) | 通过键查找值,如果找不到,则返回null |
containsKey(Object) | 判断Map中是否存在指定键 |
containsValue(Object) | 判断Map中是否存在指定值 |
Map遍历
因为没有继承Iterator,所以也就不能使用迭代器,因此,需要把Map的键和值转成Collection对象,然后再使用迭代器
Collection<Student> c = map.values();//这里用values()方法,返回值所对应的Collection视图
Set<String> key = map.keySet();//这里使用keySet()方法,返回键值对的Set视图
也可以使用entrySet()方法创建包含键值对的set视图
Set <Map.Entry<String,Student>> set = map.entrySet();
Map.Entry里面有接口方法,getKey(),getValue(),还有setValue()可以用指定的值替换当前键值对应的值
HashMap(散列映射)
HashSet就是基于HashMap进行实现,可以保证元素值得单一性,具体构造方法类似HashSet()
容器的Collection工具类
方法 | 描述 |
---|---|
Collections.sort(List o) | 需要实现比较器接口,可以对指定元素进行排序 |
Collections.binarySearch(List o,查找的值) | 返回的是输出的位置,要求List是有序的 |
Collections.reverse(List o) | 逆序排列List |
Collections.fill(List o,需要填充的值) | 把List中的所有元素换成指定元素 |
Collections.copy(List o1,List o2) | 把o2的值复制到o1 |
Iterator(迭代器)
很多地方需要用到迭代器,比如set的遍历因为没有索引和get方法,所以需要用迭代器来进行遍历
迭代器是一种设计模式,把集合排成一个序列,进行遍历而不需要了解序列的底层结构,但是这也带来了限制,基本迭代器只能进行单向移动
使用迭代器进行遍历
List<String> a = new ArrayList<String>();
for(Iterator<String> it = a.iterator();it.hasNext(); )
{
String s = it.next();
}
常用方法
方法 | 作用 |
---|---|
iterator() | 来自java.lang.Iterable接口,用于返回一个迭代器类型对象 |
next() | 获取序列中的下一个元素,每成功调用一次向后移动一个元素,如果要读取第一个需要先使用next() |
hasNext() | 检查序列中是否还有元素 |
remove() | 将迭代器新返回的元素删除 |
List<String> a = new LinkedList<String>();//使用泛型
Iterator<String> k=a.iterator();
for(;k.hasNext();)
{
String s=k.next();//如果直接使用k.remove(),将会报错,需要用k.next移动到第一个位置
System.out.println(s);
k.remove();
}
//List的遍历也可以使用以下方法,这是使用了foreach遍历,其实是把迭代器包装了以下,使得代码更加简洁,List和Set都可以使用foreach遍历
for(String s:a)
{
System.out.println(s);
}
ListIterator迭代器:继承于Iterator迭代器,支持两个方向遍历List
一般只对LinkedList或者其他链表结构使用,ArrayList因为已经可以用索引进行存取,因此无需使用此迭代器
新增方法 | 作用 |
---|---|
add() | 在即将遍历元素反方向位置插入元素 |
hasPrevious() | 看当前迭代器位置前面是否有元素 |
remove() | 删除上一次遍历的元素 |
previous() | 获得前驱元素 |
泛型
泛型是对Java语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。不像 C++ ,Java泛型不支持基本数据类型
泛型是定义了一个容器只保存单一类型,如不使用泛型,在一个List里,可以插入各种类型的对象,因为会被自动转换成Object
泛型的应用
public class DEMO {
public static void main( String[] args ){
List<String> a = new ArrayList<String>();//使用泛型
a.add("haha");
a.add(1);//会报错The method add(int, String) in the type List<String> is not applicable for the arguments (int)
}
}
可以使用泛型变量
class s <T>
{
private LinkedList<T> list = new LinkedList<T> ();
}
也可以使用泛型方法
public<T> T testGen(boolean b,T first,T second)
使用的时候
String s = testGen(true,"a","b");