java数据结构

一、数组

      一片物理上连续,大小确定的存储空间

      下标查找元素,时间上复杂度O(1)

       按值查找,时间复杂度0(n)

1、定义数组

 String[] arr=new String[]{"1","2","3"};
 String[] arr2=new String[2];
 String[][] arr3 = new String[3][5];

2、遍历数组

for (int i = 0; i < arr.length; i++) {
     String temp = arr[i];
 }

 for(int m=0;m<arr3.length;m++){
      for(int n=0;n<arr3[m].length;n++){
         String value=arr3[m][n];
     }
}

 

二、集合与数组

(1)集合与数组的区别

类别长度元素类型
数组不可变的基本数据类型,引用类型
集合可变引用类型

(2)集合与数组的转换

//数组----->集合Arrays.asList();
String[] arr=new String[10];
List<String> list=Arrays.asList(arr);

//集合------>数组  toArray();
List<String> list=new ArrayList<>();
String[] arr = (String[])list.toArray();

 

三、集合

1、集合的框架图

2、Collection是集合的顶层类

      通用方法:

public booelan   add(E e);
public void    clear();
public booelan  remove(E e);
public boolean  contains(E e);
public boolean  isEmpty();
public int  size();
public Object[]   toArray();
public Iterator<E>  iterator();

3、元素遍历方式

(1)Iterator迭代器

     在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,然后继续判断,继续取,一直把集合中的所有元素全部取出来。在迭代时可以删除元素

  主要方法:

public booelan  hasNext();
E  next();

 用法实例:

List<String>  list=new ArrayList<>();
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
    String temp=iterator.next();
}

(2)增强for也称foreach

      注:在循环时不能增删,会发生下标越界错误

for(String item:list){
    System.out.println(item);
}

4、Queue队列先进先出 

E   element()  //检索,但不删除此队列的头
boolean   offer(E e)//如果可能立即在不违反容量限制的情况下这样做的话,将指定的元素插入到队列 
                         中。 
E   peek();   //检索,但不删除,这个队列头,或返回 null如果队列为空。 
E   poll();   //检索并移除此队列的头,或返回 null如果队列为空。 
E   remove();  //检索和删除此队列的头

 

四、List

三大特点:有序元素可以重复有索引

方法:除了Collection提供的方法,还包括些自己的方法

void   add(int index,E element);
addAll(Collection<? extends E>  c)
boolean containsAll(Collection<?> c)  
E get(int index)  
int indexOf(Object o)  
E remove(int index)  
boolean removeAll(Collection<?> c)  
E set(int index, E element)  
类名底层实现特点父类
ArrayList数组查询快,增删慢,线程不安全,默认容量10,扩容1.5倍List
Vector数组查询快,增删慢,线程安全List
LinkedList链表查询快,增删慢,线程不安全List,Queue
Stack 后进先出Vector

1、ArrayList增删慢的原因?

  • add(int index,E element)在指定下标插入元素,实现是该下标后面的元素都后移一位。
  • remove(int index)删除指定下标元素,该下标之后的元素都要前进一位
  • arrayList清除从后面删除

2、LinkedList的方法

void addFirst(E e)  //在此列表的开始处插入指定的元素。 
void addLast(E e)   //将指定的元素列表的结束。 
E getFirst()  
E getLast()  
boolean offer(E e)  //将指定的元素添加到列表的尾部(最后一个元素)。
boolean offerFirst(E e)  
boolean offerLast(E e)  
E peek()  检索,但不删除,此列表的头(第一个元素)。 
E peekFirst()  
E peekLast()  
E poll()  检索并删除此列表的头(第一个元素)。 
E pollFirst() 
E pollLast() 
E pop()   从这个列表所表示的堆栈中弹出一个元素。
void push(E e)  

3、Stack的方法

E  peek   查看此堆栈顶部的对象,而不将它从堆栈中删除。 
E  pop()  在这个堆栈的顶部删除对象,并返回该对象的值作为该函数的值。 
E push(E item)  将一个项目推到这个堆栈的顶部。

 

五、Set

特点:无序元素唯一,无索引

类名底层特点父类

HashSet

哈希表查询速度快,线程不安全,初始是16Set
LinkedHashSet哈希表+链表元素有序HashSet
TreeSet红黑树  

1、HashSet

     为了保证元素的唯一性,依赖元素类的两个方法  hashCode方法equals方法

     哈希值是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址。是模拟出来得到地址,不是

      数据实际存储的物理地址)在Object类中有一个方法可以获取对象的哈希值  int   hashCode()返回对象的哈希码值。

         jdk1.8版本之前:哈希表=数组+链表

         jdk1.8版本之后:哈希表=数组+链表 

                                     哈希表=数组+红黑树(提高查询的速度)

         哈希表的存储结构:

      

2、LinkedHashSet

      底层:哈希表(数组+链表/红黑树)+链表:多了一条链表(记录元素的存储顺序),保证元素有序,但也不允许重复

      由链表保证元素有序,由哈希表保证元素唯一

 

3、TreeSet

       底层:红黑树(唯一,有序)

       为了保证元素排序,自然排序(元素具有比较性),比较器排序

(1)自然排序,compareTo方法

//实现Comparable接口,
public class Stundent implements Comparable<Stundent> {
    @Override
    public int compareTo(@NonNull Stundent o) {
        return 0;
    }
}

(2)使用比较器  Comparator接口

//构造器函数中传入实现了comparator接口
TreeSet<Student> set=new TreeSet<Student>(new Comparator<Student>(){
    
    @Override
    public int compare(Student o1, Student o2) {
        return 0;
    }
});

 

六、Map

 1、映射键到值的对象。一张Map不能包含重复的键(键唯一),每个键可以映射到至多一个值

 常用方法:

void clear() 
boolean containsKey(Object key)  
boolean containsValue(Object value)  
Set<Map.Entry<K,V>> entrySet()  
V get(Object key)  
boolean isEmpty()  
Set<K> keySet()  
V put(K key, V value)  
V remove(Object key)  
int size()  

2、Map.Entry<K,V>

     接口Entry是Map的静态内部接口,键值对

final K key;
V value;
final int hash;
HashMapEntry<K, V> next;
K getKey()   返回对应于此项的键。
V getValue()   返回对应于此项的值。 
V setValue(V value)   用指定的值替换对应于此项的值(可选操作)

3、map的遍历

(1)获取keyset

Map<String, String> maps = new HashMap<>();
Set<String> keySet = maps.keySet();
Iterator<String> iterator = keySet.iterator();
while (iterator.hasNext()) {
    String key = iterator.next();
    String value = maps.get(key);
}

(2)获取entrySet

Map<String, String> maps = new HashMap<>();
Set<Map.Entry<String, String>> entries = maps.entrySet();
Iterator<Map.Entry<String, String>> iterator = entries.iterator();
while (iterator.hasNext()) {
   Map.Entry<String, String> entry = iterator.next();
   String key = entry.getKey();
   String value = entry.getValue();
}

4、对比

类名底层特点备注
HashMap数组+链表(数组+红黑树)null键null值,线程不安全,无序 
LinkedHashMap数组+链表+链表线程不安全,有序 
HashTable哈希表不允许null键null值,线程安全,无序 
TreeMap二叉树线程不安全 

(1)HashMap

         JDK1.8之前:数组+单向链表,JDK1.8之后:数组+单向链表/红黑树(链表的长度超过8)

 

七、HashMap原理解析

1、HashMap的底层(数组+链表)

  • HashMap的主干是一个Entry数组,整体结构如下:

  • Entry的结构
final int hash;
final K key;
V value;
Node<K,V> next;
  • 数组确定下标   

       首先获取key对象的hashCode值,hashCode与数组长度的位运算获取下标,这就是元素的下标。

       注:java中所有类都继承于Object类,可以覆写hashCode方法,这是一个native方法。

  • 链表是为了解决哈希冲突

        hashCode值不同,运算出来的下标有可能相同,所以需要用链表来解决hash冲突来存储数据。下标确定之后,获取当前下标链表,遍历链表,看是否存在entry,这个entry和要插入(查找)的entry的key值是否一样(这就是key值是唯一的原因),如果没有,则这个新entry的next的值为链表的头结点,形成新的链表返回。

2、HashMap扩容,阈值0.75f

      初始值是16newSize=oldSize*2,容量一定为2的n次幂,当map中的元素总数超过容量的75%,触发扩容,扩容的时候回遍历所有的元素重新计算元素下标,添加到新的链表。

     Hashmap 优化,因为在扩容时浪费时间性能,所以可以在创建HashMap的时候指定大小,如果想要容量是10,设置值为10/0.75=14。

3、算法应用

     集合去重

 

八、HashMap的扩展

1、LinkedHashMap

        LinkedHashMap继承与HashMap,元素是有序的。

(1)LinkedHashMap的entry,双向链表

static class LinkedHashMapEntry<K,V> extends HashMap.Node<K,V> {
    LinkedHashMapEntry<K,V> before, after;
    LinkedHashMapEntry(int hash, K key, V value, Node<K,V> next) {
       super(hash, key, value, next);
    }
}

  所以,每个Entry都包含  hash,key,value,Node,before,after

(2)LinkedHashMap初始化

  • initialCapacity 初始化容量
  • accessOrder   值为false时,插入排序;值为true时,访问排序

 

2、ConcurrentHashMap

         ConcurrentHashMap底层是数组+链表,和HashMap和HashTable是一样的,但是HashMap是线程不安全的,hashTable是线程安全的,但是性能太差,而ConcurrentHashMap不仅是线程安全而且性能更高。

          锁分段技术,通过把整个Map分成N个segment,可以提供相同的线程安全,但是效率提高N倍。

3、SparseArray

         它是android内部特有的api,他 比HashMap更省内存,因为它的键只能是Interger,避免了对key的自动装箱。内部是通过两个数组来今次那个数据存储的,一个存储key,一个存储value。

private int[] mKeys;
private Object[] mValues;

key的查找是二分查找,value的值是和key的下标一样的。

sparseArray的添加时,后面的元素是以此向后移动,

删除时,并不会真的删除,是把value的设置为null。

 

九、Collections工具类

//指定列表为升序排序,根据其元素的 natural ordering。
static <T extends Comparable<? super T>>  void sort(List<T> list)  
//根据指定的比较器指定的顺序对指定的列表进行排序。  
static <T> void sort(List<T> list, Comparator<? super T> c) 

 

直通车-------java基础

直通车-------java常见算法总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值