集合
容器:数组就是一种容器而且是效率最高的,但是本身不够灵活 容量必须实现定义好
java中集合就是容器
泛型
泛型:一种约束,泛型可以省略判断、审查步骤、可读性更强
public static void main(String[] args) {
M<String> m = new M<String>();//jdk 1.7以后可以省略后面的泛型
m.set("黑",0);
m.set(111,1);//报错,提示不可以使用String以外的类型
String a = m.get(0);
String b = m.get(1);//报错
}
class M<E>{//此时E就代表String
Object[]o = new Object[5];
public void set (E e,int i){
o[i]=e;
}
public E get (int i){
return (E)o[i];
}
}
Collection接口
List接口和Set接口继承了Collection接口
List是有序、可重复容器 即可要通过下标访问元素、可以加入重复元素
Set是无序、不可重复容器
List接口的实现类:ArrayList()、LinkedList()和Vector/CopyOnWriteArrayList;
set接口的实现类: TreeSet(); HashSet();
Map接口的实现类:HashMap(); TreeMap(); HashTable();
Collection接口常用方法:
c.add(“万”);//添加万
c.remove(“万”);//移除 万 也可以写索引:c.remove(0);//删除下标为1的元素
c.size()//集合的个数
c.isEmpty()/判断是否为空/
c.contains(“万”)/是否包含 万/
c.clear();//移除集合内所有元素
list2.addAll(list1);//拿到list1中所有元素加入到list2 结果返回到list2中
list2.removeAll(list1);//删除list1和list2中相同的部分 结果返回到list2中
list2.retainAll(list1);//删除list1和list2中不相同的部分 结果返回到list2中
list1.containsAll(list2)//判断list1中是否包含list2中所有元素
List
ArrayList:
ArrayList底层是用数组来实现存储。特点:查询效率高,增删效率低且线程不安全。一般情况使用
需要频繁增删改的用LinkedList()/需要线程安全的用Vector/CopyOnWriteArrayList
ArrayList常用方法:
list.indexOf(Object o);//返回元素o的下标 如果不存在返回-1
list.lastIndexOf(Object o);//从右往左找到 返回元素o的下标 如果不存在返回-1 这个方法为了防止有重复元素
扩容:
ArrayList长度可以扩充,在长度不够时自动新建一个更长的数组 把原来的元素拷贝过去
List list = new ArrayList(100);//长度为100 不写这个参数 默认为10
ArrayList中所有的删除操作其实都是遍历数组然后通过下标判断,然后将后面的元素通过 System.arraycopy方法搬到前面
在Arraylist的添加操作中,
当数组elementData长度等于下标时新建数组设置长度为原来数组的 1.5 倍,
通过System.arraycopy方法
//把elementData数组的值放到newArray数组中,从elementData的0(第一个0)开始 放到newArray中的0(第二个0)共放elementData.length
System.arraycopy(elementData,0,newArray,0,elementData.length);
LinkedList
LinkedList底层用双向链表实现的存储。特点:查询效率低,增删改效率高,线程不安全。
previous 为上一个 next 为下一个 element 为当前
添加:
第一次添加元素则 第一个元素和最后一个元素都为当前元素:first=node; last=node;
不是第一次添加元素:node.previous=last;node.next=null;last.next=node;last=node;
查:查询第一个元素为:first.next 第二个为: first.next.next ……
可以先比较当前索引与集合中元素数量大小:
Node t = null;
if (n<=(size>>1)){
t = first;
for (int i=0;i<n;i++){
t=t.next;
}
}else {
t = last;
for (int i=size-1;i>n;i--){
t=t.previous;
}
}
Node temp = getNode(n);
return temp!=null?temp.element:null;
根据索引添加:
public void add(int index,Object o){
Node Newnode = new Node(o);
Node temp = getNode(index);
if (temp!=null){
Node up = temp.previous;
up.next=Newnode;
Newnode.previous=up;
Newnode.next=temp;
temp.previous=Newnode;
}
size++;
}
删除:remove 通过索引删除某个元素:
Node temp = getNode(n);
if (temp!=null){
Node up = getNode(n).previous;//这个元素的上一个
Node down = getNode(n).next;//这个元素的下一个
if (up!=null){
up.next=down; //直接跳过当前元素 把上一个元素的next设置成下一个元素
}
if (down!=null){
down.previous=up;//直接跳过当前元素 把下一个元素的previous设置成上一个元素
}
if (n==0){
first=down;
}
if (n==size-1){
last=up;
}
size--;
}
Map
HashMap
map中的key 键不能够重复,如果重复则会覆盖旧的
是否重复根据equals方法来判断
HashMap底层实现采用了哈希表,是一种非常重要的数据结构
哈希表基本结构是 数组+链表
存储过程:put(key,value)
调用key对象的hashcode()方法得出hashcode哈希码,哈希码通过HashMap的hash()方法计算出对应的哈希值 hash
哈希值 hash 要求在0-数组长度-1 之间 也就是说 hash等于hashcode % 数组长度 (早期的HashTable采用的算法)
后来采用取余方式 : hash值等于hashcode & (数组长度-1) 这个是有个条件:首先约定数组长度必须为2的整数幂
jdk8以后当数组长度大于8时候 链表会转化为红黑树 这样又大大提高了查找效率
假如算出的是15 那么就在 HashMap的Entry[]数组中下标为15的元素的的地方创建一个链表来存储这个元素
链表中有 hash key value next 第二次存放hash为15的元素时 第一个创建的元素的next就是他的hash
取数据:get(key):
1.获得key的hashcode,通过hash()散列算法得到hash值,进而定位到数组的位置。
2.在链表上挨个比较key对象。调用equals()方法,将key对象和链表上所有节点的key对象进行比较,
直到碰到返回true的节点对象为止
3.返回equals()为true的节点对象的value对象
Java中有规定 两个相同的对象即:t.equals(y)为ture时 必须具有相等的hashCode。
TreeMap 一般用于排序,会按照key自增的方式排序 不常用
Comparable接口 需要泛型
HashTable 线程安全,效率低。不允许key或者value为null 方法和hashmap一样 只是这几点不同
HashMap 线程不安全,效率高,允许key或者value为null
HashMap常用方法:
添加方法: m.put(key,value)
获取:m.get(key)
判断是否为空:m.isEmpty()
是否包含key为2的 m.containsKey(2);
是否包含value为four的 m.containsValue(“four”);
Set
Set接口继承于Collection接口 set接口没有顺序不能重复
没有顺序所以要查找的话需要遍历去对比
不能重复所以当新元素添加时与就元素equals()为ture时 不能添加
HashSet
HashSet中的方法和Collection一样 只是不可重复没有顺序
可以说HashSet是简化版的HashMap
可以理解为HashSet添加的元素都是HashMap中的key,再HashMap中key就是不可重复的
TreeSet
TreeSet底层源码中:
public TreeSet(){
this(new TreeMap<E,Object> ()); E就是默认key
}
与 TreeMap一样 自动排序
Iterator迭代器
public static void testIteratorList() {
List<String> list = new ArrayList<>();
list.add("a00");
list.add("v");
//使用迭代器遍历list
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) { //list.iterator() 获取迭代器 相当于初始化 iterator.hasNext()判断是否有下一个
String temp = iterator.next();//iterator.next() 即返回当前对象 并且游标也会指向下一个
System.out.println(temp);
}
//如果需要遍历的时候删除元素 建议使用:
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
Object obj = iterator.next();
iterator.remove();
System.out.println(obj);
}
}
遍历set的操作和list一样 只有Map有一些不同:
public static void testIteratorMap(){
Map<Integer,String> map = new HashMap<>();
map.put(100,"ss");
map.put(200,"cc");
map.put(300,"dd");
//第一种遍历Map方式
Set<Entry<Integer,String>> ss =map.entrySet();//entrySet实现了Set接口,里面存放的是键值对。一个K对应一个V。
for (Iterator<Entry<Integer,String>> ite =ss.iterator();ite.hasNext();){
Entry<Integer,String> temp = ite.next();
System.out.println(temp.getKey()+":"+temp.getValue());
}
//第二种方式
Set<Integer> keySet = map.keySet();//keySet里面存放了K
for (Iterator<Integer> iter =keySet.iterator();iter.hasNext();){
Integer key = iter.next();
System.out.println(key+":"+map.get(key));
}
Collections工具类
Collections工具类常用方法
sort(List); //对List内容器按照递增方式排序
shuffle(list);//随机排列list中的元素
reverse(list);//逆序排列
binarySearch(list,“b”));//二分法查找“b” 并返回索引(下标)
测试:
public static void main(String [] args){
List<String> list = new ArrayList<>();
for (char a='a';a<'g';a++){
String s = String.valueOf(a);
list.add(s);
}
System.out.println(list);
Collections.shuffle(list);//随机排列list中的元素
System.out.println(list);
Collections.reverse(list);//逆序排列
System.out.println(list);
Collections.sort(list);//按照递增方式排序
System.out.println(list);
System.out.println(Collections.binarySearch(list,"a"));//二分法查找“a” 并返回索引(下标)
}
使用容器来存储表格数据:
Map和List结合存储表格:
ORM思想的简单实验:map表示一行数据,多行数据是多个map 将多个map放到一个list中
public static void main(String[] args) {
Map<String,Object> map = new HashMap<>();
map.put("ID",1001);
map.put("姓名","李四");
map.put("薪资",30000);
map.put("日期","2021-01-07");
Map<String,Object> map2 = new HashMap<>();
map2.put("ID",1002);
map2.put("姓名","张三");
map2.put("薪资",3000);
map2.put("日期","2021-02-07");
Map<String,Object> map3 = new HashMap<>();
map3.put("ID",1003);
map3.put("姓名","王五");
map3.put("薪资",20000);
map3.put("日期","2020-08-07");
List<Map<String,Object>> list = new ArrayList<>();
list.add(map);
list.add(map2);
list.add(map3);
for (Map<String,Object> m:list
) {
for (String i:m.keySet()
) {
System.out.print(i+":"+m.get(i)+"\t");
}
System.out.print("\n");
}
}
JavaBean和List\Map结合存储表格:
ORM思想的简单实验:javabean表示一行数据,多行数据是多个javabean 将多个javabean放到一个list\map中
class User{
private int id;
private String name;
private double salary;
private String hiredate;
有参无参构造方法
set get 方法
toString 方法
}
public static void main(String[] args) {
User user1 = new User(1001,"张三",2134,"2021-01-07");
User user2 = new User(1002,"李四",10000,"2021-12-07");
User user3 = new User(1003,"王五",2134,"2021-08-07");
// 与List结合:
List<User> list = new ArrayList<>();
list.add(user1);
list.add(user2);
list.add(user3);
for (Iterator<User> u=list.iterator();u.hasNext();){
User a = u.next();
System.out.println(a);
}
// 与Map结合:
Map<Integer,User> map = new HashMap<>();
map.put(1001,user1);
map.put(1002,user2);
map.put(1003,user3);
Set<Entry<Integer, User>> set = map.entrySet();
for (Iterator<Entry<Integer,User>> e = set.iterator();e.hasNext();){
Entry<Integer,User> en = e.next();
System.out.println(en);
}