数组缺点:增加删除效率低
优点:查询效率高
集合:把相同特征的个体整合到一起
数据结构
逻辑结构
定义:指反映数据元素之间的逻辑关系的数据结构,其中的逻辑关系是指数据元素之间的前后关系,而与他们在计算机中的存储位置无关
线性结构
定义:有且只有一个开始结点和一个终端结点,并且所有结点最多只有一个直接前驱和一个直接后驱
非线性结构
定义:一个结点元素,对应多个直接前驱和多个直接后驱
存储结构(物理结构)
定义:指数据的逻辑结构在计算机存储空间的存放形式,也就是真正在计算机存储器中如何存储的
顺序存储
定义:把逻辑上相邻的节点存储在物理位置相邻的存储单元中
链式存储
定义:数据元素的存储对应的是不连续的存储空间,每个存储节点对应一个需要存储的数据元素。每个结点是由数据域和指针域组成。逻辑上相邻的节点物理上不必相邻
索引存储
定义:除建立存储结点信息外,还建立附加的索引表来标识结点的地址。就像是字典的偏旁查询
散列存储
可以直接找,可以用索引找
算法
定义:解题方案的准确和完整的描述,是一系列解决问题的清晰指令,简单说就是计算机解题的过程
特性:五个基本特征:输入、输出、有穷性、确定性 和可行性
集合(容器)
接口Collection
接口中常用的方法
/*
接口中常用的方法
增加:add(E e) addAll(Collection<? extends E> c)
删除:clear() remove(Object o)
修改:
查看:iterator() size()
判断:contains(Object o) equals(Object o) isEmpty()
*/
Collection col=new ArrayList();
col.add("java");
col.add(12);//自动装箱Integer i=12
col.add(9.8);
System.out.println(col);
System.out.println(col.size());
System.out.println(col.isEmpty());
Collection col2=new ArrayList();
col2.add(1);
col2.add(2);
col2.add(8);
col.addAll(col2);
System.out.println(col);
col.remove(1);
System.out.println(col);
//遍历1
for (Object o:col){
System.out.println(o);
}
//遍历2,使用迭代器iterator
Iterator it = col.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
子接口1–List
下面有三个实现类ArrayList、Vector和LinkedList
/*
增加 add(int index, E element)
删除 remove(int index) remove(Object o)
修改 set(int index, E element)
查看 get(int index)
判断
*/
List list=new ArrayList();
list.add("java");
list.add("html");
list.add("css");
list.add("js");
System.out.println(list);
list.add(1,"or");
System.out.println(list);
list.remove("java");
System.out.println(list);
//遍历
//方法1 普通for
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("-----------------");
//方法2 增强for
for (Object o:list){
System.out.println(o);
}
System.out.println("-----------------");
//方法3 迭代器
Iterator it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
实现类ArrayList和Vector(现在已经淘汰了)
ArrayList
底层结构:数组
原理:数组的扩容
JKD1.2开始
效率高,线程不安全
Vector
底层结构:数组
原理:数组的扩容
JKD1.0开始
效率低,线程安全(底层加了synchronized)
ArrayList特点
ArrayList可以看成自动增长容量的数组,其底层实现就是数组
- 新增数据空间判断,新增数据的时候判断是否有空闲空间存储
- 扩容需要申请新的连续空间
- 把老的数组复制过去
- 新加内容
- 回收老的数组空间
ArrayList在初始化的时候最好指定长度,指定长度性能比不指定长度性能好很多,数据量越大越明显,因为这样不用重复申请空间,复制数组,摧毁老的分配空间了.
泛型
// // 多态:扩展性好
// List list = new ArrayList();
// //不需要扩展性好,想用ArrayList中特有的方法的时候,用这个方式
// ArrayList al=new ArrayList();
/*
1.泛型:加入了<>表示泛型后,说明集合中只能放这种数据类型
2.为啥用 <> :() {} [] "" ''
3.在没有加入泛型的时候,会报黄色的警告
*/
ArrayList<String> al=new ArrayList<String>();
al.add("java");
al.add("html");
al.add("js");
Iterator it = al.iterator();
while (it.hasNext())
System.out.println(it.next());
泛型的分类
泛型类
public class fanxing<AA> {
//普通的类后面加上一个泛型,泛型的累不确定,就变成了一个泛型类
//并且AA的类型不确定,创捷对象的时候确定
}
class Demo{
public static void main(String[] args) {
//在创建对象的时候,不使用泛型,可以,但有黄色警告
fanxing fx1=new fanxing();
//在创建对象的时候,使用泛型
fanxing<String> fx2=new fanxing<String>();
}
}
泛型方法
public class fanxing<AA> {//泛型类
public void a(){}
public void b(AA a){}
public <BB> void c(BB b){}
public void f(AA[] a){}
public <Q> Q[] g(Q...q){
for (Object o:q){
System.out.println(o);
}
return q;
}
}
class Demo{
public static void main(String[] args) {
fanxing<String> fx=new fanxing<String>();
fx.a();
fx.b("asdf");
//解决了方法名相同,形参列表个数相同的 方法的 重载问题
fx.c(12);
fx.c("as");
fx.c(9.8);
fx.f(new String[]{"a","b","c"});
//解决了方法名相同,形参列表不同的 方法的 重载问题
fx.g(12,23,34);
fx.g("a","b","c");
}
}
泛型接口
public interface FanXingInterface<AA> {//泛型接口
}
class A implements FanXingInterface{}//不写泛型,出黄色警告
class B implements FanXingInterface<String>{}//带泛型可以直接用
class C<BB> implements FanXingInterface<BB>{}//C变成泛型类
泛型的高级应用
public class Test5 {
public static void main(String[] args) {
ArrayList<person> al=new ArrayList<person>();
al.add(new person("lili",19));
al.add(new person("nana",16));
al.add(new person("lulu",17));
bianli(al);
ArrayList<Student> al2=new ArrayList<Student>();
al2.add(new Student("lili",190.8));
al2.add(new Student("nana",170.1));
al2.add(new Student("lulu",180.2));
bianli(al2);
}
//泛型的上限 Student是person的子类
public static void bianli(ArrayList<? extends person> al){
for (Object p:al
) {
System.out.println(p);
}
}
}
LinkedList类
底层:双向链表
模拟LinkedList
public class Node {
private Object previous;//前一个节点的地址
private Object obj;//节点内容
private Object next;//后一个节点的地址
public Object getPrevious() {
return previous;
}
public void setPrevious(Object previous) {
this.previous = previous;
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
public Object getNext() {
return next;
}
public void setNext(Object next) {
this.next = next;
}
}
public class MyLinkedList {
private Node first;//链表中第一个节点
private Node last;//链表中最后一个节点
public Node getFirst() {
return first;
}
public void setFirst(Node first) {
this.first = first;
}
public Node getLast() {
return last;
}
public void setLast(Node last) {
this.last = last;
}
public void add(Object o){
if (first==null){//添加的是第一个节点
Node n=new Node();
n.setPrevious(null);
n.setObj(o);
n.setNext(null);
first=n;
last=n;
}else{//添加的不是第一个节点
Node n=new Node();
n.setPrevious(last);
n.setObj(o);
n.setNext(null);
last.setNext(n);
last=n;
}
}
public static void main(String[] args) {
MyLinkedList ml=new MyLinkedList();
ml.add("aaa");
ml.add("bbb");
ml.add("ccc");
System.out.println(ml);
}
}
LinkedList链表特点
LinkList是一个双链表,在添加和删除元素时由比ArrayList更好的性能.但在get与set方面弱于ArrayList当然,这些对比都是值数据量很大或者操作很频繁
- 链表不需要连续的空间
- 大小不固定
迭代器ListIterator
比起Lterator,可以一边迭代一边插入元素,还可以反向遍历
public static void main(String[] args) {
ArrayList<String> al=new ArrayList<String>();
al.add("java");
al.add("html");
al.add("js");
al.add("servlet");
ListIterator<String> it = al.listIterator();
while (it.hasNext()){
String str=it.next();
if("js".equals(str)){
it.add("oracle");
}
}
while (it.hasPrevious()){
System.out.println(it.previous());
}
System.out.println(al);
}
子接口2–Set
下面有两个类:HashSet和TreeSet
HashSet
底层用的是HashMap
无序且唯一,效率高
自定义的引用类型必须重写hashCode和equals方法
public static void main(String[] args) {
HashSet<String> hs = new HashSet<String>();
hs.add("java");
hs.add("html");
hs.add("css");
hs.add("java");
hs.add("js");
hs.add("servlet");
System.out.println(hs);//无序,唯一
System.out.println(hs.size());
}
不同底层的hashCode方法:
Integer
public static int hashCode(int value) {
return value;//返回的就是底层包装的那个基本类型int对应的数值value
}
Double
public static int hashCode(double value) {
long bits = doubleToLongBits(value);
return (int)(bits ^ (bits >>> 32));
}
String:底层的char类型数组遍历后乘系数相加计算
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
student:各个属性拼起来之和
@Override
public int hashCode() {
return Objects.hash(name, age, height);
}
LinkedHashSet
有序且唯一
public static void main(String[] args) {
LinkedHashSet<Integer> hs=new LinkedHashSet<Integer>();
hs.add(12);
hs.add(4);
hs.add(6);
hs.add(7);
hs.add(2);
hs.add(18);
hs.add(6);
System.out.println(hs);//有序,唯一
System.out.println(hs.size());
}
TreeSet
底层:二叉树(红黑树),自定义的类放入集合中,要实现内部比较器或者外部比较器
底层是TreeMap
public static void main(String[] args) {
TreeSet<Integer> ts = new TreeSet<Integer>();
ts.add(12);
ts.add(6);
ts.add(15);
ts.add(3);
ts.add(12);
ts.add(1);
System.out.println(ts);//无序(没有按照输入顺序输出) 有序(按照从小到大的顺序输出) 唯一
System.out.println(ts.size());
}
public static void main(String[] args) {
//Comparator<Student> com=new bijiao01();
TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getName().compareTo(o2.getName());
}
});
ts.add(new Student("blili",150.9,21));
ts.add(new Student("clili",190.9,18));
ts.add(new Student("alili",130.9,16));
ts.add(new Student("clili",180.9,19));
System.out.println(ts);
System.out.println(ts.size());
}
class bijiao01 implements Comparator<Student>{//外部比较器,a
@Override
public int compare(Student o1, Student o2) {
return o1.getAge()-o2.getAge();
}
}
接口Map
遍历方法:entrySet() get(Object key) keySet() values()
public static void main(String[] args) {
/*
HashMap:特点:按照key来说的,key底层遵照的是哈希表(散列表)原理 key 唯一无序
如果你将一个自定义的类放入key中,这个类要重写hashcode方法,equals方法
常用方法
增加:put(K key, V value)
删除:clear() remove(Object key)
修改:
查看:entrySet() get(Object key) keySet() values()
判断:containsKey(Object key) containsValue(Object value)
<Integer, String> 键值对 <K,V>
*/
Map<Integer, String> m = new HashMap<Integer, String>();
m.put(1001,"lili");
m.put(1002,"nana");
m.put(1003,"lulu");
m.put(1001,"feifei");
m.put(900,"mingming");
System.out.println(m);
System.out.println(m.isEmpty());
System.out.println(m.size());
//对集合遍历
//对key进行遍历
Set<Integer> keySet = m.keySet();
for (Integer i:keySet){
System.out.println(i);
}
//对value进行遍历
Collection<String> values = m.values();
for (String s:values){
System.out.println(s);
}
for (Integer i:keySet){
System.out.println(m.get(i));
}
//对key,value成对遍历
Set<Map.Entry<Integer, String>> es = m.entrySet();
for (Map.Entry<Integer, String> en:es){
System.out.println(en.getKey()+" "+en.getValue());
}
}
子类1-HashMap
HashMap:特点:按照key来说的,key底层遵照的是哈希表(散列表)原理 key 唯一无序
如果你将一个自定义的类放入key中,这个类要重写hashcode方法,equals方法
子类LinkedHashMap
有序,按照输入顺序输出
子类2-TreeMap
底层:key遵照二叉树(红黑树原理),如果自定义的类作为key存放,要实现内部比较器或者外部比较器
public static void main(String[] args) {
TreeMap<Student, String> tm = new TreeMap<Student,String>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge()-o2.getAge();
}
});
tm.put(new Student("lili",19),"班长");
tm.put(new Student("nana",16),"文艺委员");
tm.put(new Student("lili",12),"英语委员");
tm.put(new Student("lulu",12),"体育委员");
System.out.println(tm);
}
工具类Collections
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();
al.add("apple");
al.add("banana");
al.add("java");
System.out.println(al);
//addAll 添加
Collections.addAll(al,"merry","lili","abc");
System.out.println(al);
Collections.addAll(al,new String[]{"nihao","jsp"});
System.out.println(al);
//binarySearch 二分查找
System.out.println(Collections.binarySearch(al,"lili"));//不准确 要对排序后的查找
//sort 排序
Collections.sort(al);
System.out.println(al);
System.out.println(Collections.binarySearch(al,"abc"));
System.out.println(Collections.binarySearch(al,"aaaa"));//找不到 返回负数
//copy 复制
ArrayList<String> sl=new ArrayList<String>();
Collections.addAll(sl,"a","b","c","d","e","a","b","c","d","e");
System.out.println("==========");
System.out.println(al);
System.out.println(sl);
Collections.copy(sl,al);//sl的长度必须大于al的长度才能赋值替换
System.out.println(al);
System.out.println(sl);
//fill 填充
System.out.println(al);
Collections.fill(al,"java");//将al里所有的元素都变成了java
System.out.println(al);
}