------- android培训、java培训、期待与您交流! ----------
1,基础知识
|--1,数组的优缺点
数组长度不可变
数组不能添加删除元素
数组没有操作方法(查看数组中某个元素是否存在等方法)
数组中的元素在内存中是邻居,索引速度天下无敌!
|--2.1 常见的数据结构
1 常见数据结构有哪些
栈、队列、数组、链表
2 栈(Last In First Out)
后进先出,最上面的元素我们叫栈顶元素!
出栈(弹栈),就是把栈顶元素从栈中移除,并返回。
压栈,就是把一个新元素放到栈顶位置。
3 队列(FIFO)
先进先出!
没底的管道!
4 数组
数组索引元素的速度天下无敌!
arr[10] – 快速最快!
如果我们需要向数组插入和删除元素,那么就需要copy数组。
5 链表
链表元素在内存中不是邻居,链表头元素知道下一个元素的地址,下一个元素又知道下下元素的地址,最后一个元素,即链表尾,它的下一个元素是null。
链表的索引速度很慢,但插入和删除元素快速很快。
|--2.2 哈希表结构
1 桶数组
哈希表是一个桶数组,也就是说一个哈希表中有多个桶!
每个桶可以存放多个元素。可以把桶理解为链表(集合)!这样整个哈希表就是拥有多个链表的集合了。
2 计算桶位
哈希表中有很多桶,即一个桶数组。所谓桶位就是对应桶数组的下标!
3 添加元素的流程
当把元素添加到哈希表中时,需要先找到元素对应的桶位,然后判断这个桶中是否存在这个元素,如果元素在桶中已经存在,那么添加失败;否则添加成功!
获取元素的哈希码值(使用元素的hashCode()方法);
通过哈希码值计算桶位(可以把哈希码值理解为就是桶位);
遍历桶中元素,使用元素的equals()方法,验证元素是否在桶中已经存在;
存在则添加失败,否则把元素添加到桶中。
4 添加元素的问题
HashSet<Person> set = new HashSet<Person>();
Person p1 = new Person(“zhangSan”, 23, “male”);
Person p2 = new Person(“zhangSan”, 23, “male”);
set.add(p1);
set.add(p2);
上面代码中set.add(p2)的结果会添加成功!也就是说HashSet会认识p1和p2是两个不同对象。如果想让上面代码中set.add(p2)添加失败,我们需要让HashSet认为p1和p2是相等的。
set.add(p2):调用p2的hashCode()方法获取哈希码,通过哈希码找到桶。如果p1与p2的hashCode()不同,那么p2找到的桶就与p1找到的桶不同。
循环遍历p2对应桶中所有元素,使用equals()比较,如果没有相同元素,那么添加p2到这个桶中。
结论:就算p1.equals(p2)结果为true,但p1.hashCode() != p2.hashCode(),那么也是枉然!
5 HashSet保证元素唯一性
如果两个对象的hashCode()相等,并且使用equals()方法比较返回true,那么这两个对象是相等的。
|--2.3 二叉树
1 什么是二叉树
二叉树也是一种树状结构。
二叉树中每个节点最多有两个子节点。
二叉树中每个节点都比自己左边节点的值大,比右边节点的值小。
2 添加元素
添加进来的第一个元素就是根节点;
然后再添加第二个元素时,与根节点进行比较,如果比根节点大,那么放到根节点的右侧子节点位置;如果比根节点小,那么放到根节点左侧子节点位置;如果与根节点相等,那么添加失败。
添加第三个元素时,先与根比较:
如果比根小,那么再与根的左侧子节点进行比较:
大于左侧节点,新元素放到左节点的右节点位置;
小于左节点,放到左节点的左节点位置;
等于左节点,那么添加失败。
如果比根大,那么再与根的右侧子节点进行比较:
大于右侧节点,新元素放到右节点的右节点位置;
小于左节点,放到左节点的左节点位置;
等于左节点,那么添加失败。
如果等于根节点,那么添加失败。
2. 泛型
|--1. 继承泛型的方法
|---1.1 继承泛型类
程序如下:
/*
* 类型参数的名称,都是一个字母。 一般程序员都用T,表示type。 而在Java集合类中用E,表示element
*
* 持有对象 1创建A类对象时需要给T赋值 2继承A类时需要给T赋值 3其实都可以不赋值,那么就相当于赋值为Object
*/
class A<T> {
T field;
public A(T t) {
field = t;
}
public T get() {
return field;
}
}
// B不是泛型类,所以没有类型变量,那么你也只能给A赋值为常量
class B extends A<String> {
public B() {
super("hello");
}
}
// C是一个泛型类,C可以有两种选择,可以使用本类的类型变量来给A赋值
// 也可以用一个常量来赋值!
class C<T> extends A<T> {
public C(T t) {
super(t);
}
}
|---1.2 继承泛型方法
程序如下:
interface D<T> {
public T fun1();
public void fun2(T t1, T t2);
}
class E implements D<String> {
@Override
public String fun1() {
return null;
}
@Override
public void fun2(String t1, String t2) {
}
}
|---2. 泛型方法
程序如下:
public class FanXing {
public static void main(String[] args) {
MyClass.fun("Hello World");
}
}
class MyClass{
public static <T> void fun(T t){
// <T>写在返回值之前
System.out.println(t);
}
}
|---3. 泛型边界
程序如下:
import java.math.BigInteger;
public class Demo3 {
public static void main(String[] args) {
AA aa3 = new AA();
aa3.set(100);
int i = (Integer)aa3.get();
System.out.println(i);
}
}
// 边界可可以是多个,那么就是说类型参数需要是符合两个类型,也就是说,必须其中至少有一个是接口类型。
class AA<T extends Number & java.io.Serializable> {
// 这样定义保证了泛型在一定的范围内使用
// 比如继承了Number就可以在该类中使用Number的方法了
T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}