集合框架 LinkedList源码

集合框架

LinkedList源码

双向链表 : 查询慢,增删快

成员变量

transient Node<E> first;  //链表头节点元素
transient Node<E> last;   //链表尾节点元素

内部类Node

Node 节点对象
private static class Node<E> {
    E item; // 存储元素 
    Node<E> next; // 记录下一个元素地址
    Node<E> prev; // 记录上一个元素地址

    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

add方法

 void linkLast("abc") {
     final Node<E> l = last; //记住最后一个节点
     final Node<E> newNode = new Node<>(l, "abc", null);// 上一个,数据,下一个元素
     last = newNode; //新建立节点对象,赋值给最后一个节点
     if (l == null)
     	first = newNode;
     else
     	l.next = newNode;
     size++;
     modCount++;
}

get(1) 方法

Node<E> node(1) {
    if (1 < (size >> 1)) {
   	 	Node<E> x = first;
    for (int i = 0; i < 1; i++)
    	x = x.next;
      return x;
    } else {
   	 Node<E> x = last;
    for (int i = size - 1; i > index; i--)
    	x = x.prev;
      return x;
    }
}

Collections工具类

java.util.Collections 集合操作的工具类,提供方法来操作集合,方法全部是静态方法

方法 :

  • static void shuffle(List list) 集合元素随机排列
  • static void sort(List list) 集合中元素的自然顺序排序
  • static void sort(List list,Comparator c) 比较器的顺序进行排序
  • static 传递什么返回什么 synchronized开头(传递集合) 线程不安全集合,变成安全的集合
    • Comparator 是比较器接口, 自定义实现类,重写方法
	public static void main(String[] args) {
		List<Person> list = new ArrayList<Person>();
		list.add(new Person("a",10));
		list.add(new Person("b",9));
		list.add(new Person("b",12));
		list.add(new Person("b",11));
		list.add(new Person("b",10));
		System.out.println(list);
		//static void sort(List list,Comparator c) 比较器的顺序进行排序 
		Collections.sort(list, new Comparator<Person>() {
			public int compare(Person p1,Person p2) {
				
				return p1.getAge() - p2.getAge();
			}
		});
		
		System.out.println(list);
	}
}
//接口的实现类,重写方法,泛型<T> 写要比较对象
class MyComparator implements Comparator<Person>{
	//方法的参数是两个对象, 参数比较的对象
	public int compare(Person p1,Person p2) {
		//System.out.println(p1.getAge() - p2.getAge());
		return p1.getAge() - p2.getAge();
	}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1nDgpEm9-1595421932871)(images/比较器排序.jpg)]

增强for循环

增强型的for循环,出现在JDK1.5版本.

java.lang.Iterable 接口 实现这个接口允许对象成为 “foreach” 语句的目标。 含数组

谁是接口的实现类 : Collection继承接口Iterable

格式 :

for(数据类型 变量名 :  集合或者数组){

}

好处 : 减少代码量

弊端 : 无索引,不能修改容器中的元素内容

遍历数组

/*
*  增强for循环 遍历数组
*/
public static void array() {
    int[] arr = {1,3,5,7,9};
    for(int i : arr) {
    	System.out.println(i+1);
    }
    System.out.println(arr[0]);
}

遍历集合

    /*
	 * 增强for循环 遍历集合 
	 */
	public static void list() {
		List<String> list = new ArrayList<String>();
		list.add("how");
		list.add("do");
		list.add("you");
		list.add("do");
		for(String s : list) {
			System.out.println(s);
		}
		System.out.println("==========");
		
		List<Person> listPerson = new ArrayList<Person>();
		listPerson.add(new Person("a1",101));
		listPerson.add(new Person("a2",102));
		listPerson.add(new Person("a3",103));
		listPerson.add(new Person("a4",104));
		for(Person p : listPerson) {
			System.out.println(p);
		}
	}

增强for循环是个假象

属于编译特效 : javac搞事情

for遍历数组 : javac 编译为传统for形式

for遍历集合 : javac 编译为迭代器

泛型技术

JDK1.5出现的新特性(generic), 泛型技术是一种安全机制,保证程序的安全运行

不使用泛型,出现的安全问题

public static void main(String[] args) {
    List list = new ArrayList(); // 没有使用泛型
    list.add("a") ; //什么类型都可以接收
    list.add("cc");
    list.add("yretrdas");
    list.add("32erg");
    list.add("hgdf");
    list.add(1);

    Iterator  it = list.iterator();
    while(it.hasNext()) {
        Object obj = it.next();
        String s = (String)obj;
        System.out.println(s.length());
    }
}

泛型的写法格式

类名<要存储的数据类型> 变量名  = new 类名<要存储的数据类型>();
注意 : 数据类型,必须是引用类,不能写基本类型 Integer
注意版本 : JDK1.7开始,后面的类型可以省略不写  new 类名<>(); 建议写

作用 : 如何保证安全性 : 强制集合存储指定的数据类型

泛型的好处

  • 强制集合存储指定的数据类型, 类型不匹配,编译失败
  • 安全问题,由运行时期,提前到编译时期
  • 避免了数据类型的强制转换
  • 锁定了数据类型, for增强的写法

泛型中的 E, T , K , V含义

E : Element元素 , T : Type类型 , K : Key键, V : Value值

实际的表现 : 是一个未知的数据类型而已,等待程序人员指定类型

例子 : ArrayList

ArrayList<String> al = new ArrayList<String>();

源码 : public class ArrayList<E> 继承父类 实现接口...
      public boolean add(E e) 
      
      public class ArrayList<String> 继承父类 实现接口...
      public boolean add(String e)

泛型类和泛型方法(自定义)

/*
 *  <Q> 等待传递数据类型
 */
public class Factory<Q> {
	
	private Q qq;
	
	/*
	 * 静态方法,泛型不能和类上的相同
	 * 静态不能调用非静态的问题
	 */
	public static <T> void print(T q) {
		System.out.println(q);
	}
	
	/*
	 * 方法中使用的泛型,和类上的不同
	 * 单独定义这个类型
	 */
	public <T> void printT(T t) {
		System.out.println(t);
	}

	public void printQ(Q q) {
		System.out.println(q);
	}

	public Q getQq() {
		return qq;
	}

	public void setQq(Q qq) {
		this.qq = qq;
	}
	
}

public static void main(String[] args) {
    //创建对象Factory
    Factory<Integer> fi = new Factory<Integer>();
    fi.printQ(123);

    Factory<String> fs = new Factory<String>();
    fs.printQ("abc");

    fi.setQq(1);
    fi.getQq();

    fi.printT(true);

    Factory.print(1.5);
}

泛型接口

  • 实现类实现接口,不实现泛型

    public interface MyInterface <E>{
    	public abstract void inter(E e);
    }
    
    //实现类,实现接口,不实现泛型
    class MyImpl<E> implements MyInterface<E>{
    	public void inter(E e) {
    		System.out.println(e);
    	}
    }
    
    
  • 实现类实现接口,实现泛型

    public interface MyInterface <E>{
    	public abstract void inter(E e);
    } 
    //实现类,实现接口,实现泛型
    class MyImpl2 implements MyInterface<Integer>{
    	public  void inter(Integer i) {
    		System.out.println(i);
    	}
    }
    
    

泛型通配符

泛型的通配符是 ? 匹配任何数据类型. 泛型使用通配符? ,什么都可以接收

但是遍历取出的时候, 方法next()返回Object类型,不能强制转换

适合于遍历输出

public static void main(String[] args) {
    // 定义2个集合,1个存储字符串,1个存储整数
    List<String> stringList = new ArrayList<String>();
    stringList.add("a");
    stringList.add("b");

    List<Integer> integerList = new ArrayList<Integer>();
    integerList.add(1);
    integerList.add(2);

    iterator(stringList);
    iterator(integerList);
}

// 一个方法,同时迭代器2个集合
public static void iterator(List<?> list) {
    //迭代器的泛型,和集合泛型一致
    Iterator<?> it = list.iterator();
    while(it.hasNext()) {
        //迭代器取出元素: 方法 next() 返回值是什么类型
        Object obj = it.next();
        System.out.println(obj);
    }
}

泛型限定

需求 : 面向对象课程中,曾经完成过一个例子 (抽象类 abstract class) 公司类 : 开发部,财务部

定义2个集合, 分别存储开发部对象和财务部对象.

使用1个方法,同时遍历2个集合, 遍历的同时可以调用对象的方法 work()

  • ? extends E 泛型可以是E类型,或者是E子类, 泛型的上限限定

  • ? super E 泛型可以是E类型,或者是E父类, 泛型的下限限定

    public static void main(String[] args) {
    		//  定义2个集合, 分别存储开发部对象和财务部对象.
    		List<Development> devList = new ArrayList<Development>();
    		List<Finance> finList = new ArrayList<Finance>();
    		
    		//创建开发部对象
    		Development d1 = new Development();
    		d1.setName("张三");
    		d1.setId("开发部001");
    		
    		Development d2 = new Development();
    		d2.setName("李四");
    		d2.setId("开发部002");
    		
    		//创建财务部对象
    		Finance f1 = new Finance();
    		f1.setName("翠花");
    		f1.setId("财务部001");
    		
    		Finance f2 = new Finance();
    		f2.setName("翠花2");
    		f2.setId("财务部002");
    		
    		//对象存储到集合
    		devList.add(d1);
    		devList.add(d2);
    		finList.add(f1);
    		finList.add(f2);
    		
    		iterator(devList);
    		iterator(finList);
    	}
    	
    	/*
    	 *  使用1个方法,同时遍历2个集合, 遍历的同时可以调用对象的方法 work()
    	 *  ? 表示通配符,可以接收任意类型, 但是 ? 接收的类型必须是 Company的子类
    	 */
    	public static void iterator(List<? extends Company> list) {
    		Iterator<? extends Company> it = list.iterator();
    		while(it.hasNext()) {
    			//next() 方法取出就不会是Object, 是确定的类型Company
    			Company c = it.next();
    			c.work();
    		}
    	}
    
    

数据结构红黑树 (Red - Black Tree)

平衡二叉树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lttL1FCD-1595421932876)(images/平衡二叉树.jpg)]

红黑树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yAvNxjtA-1595421932878)(images/红黑树.png)]

Set集合

java.util.Set 接口, 继承父接口Collection

Set集合特点:

  • 不包含重复元素
  • 没有索引

Set接口方法

Set接口的方法和父接口Collection方法,完全一样

public static void main(String[] args) {
		//Set接口和实现类HashSet创建对象
		Set<String> set = new HashSet<String>();
		set.add("abc");
		set.add("how");
		set.add("are");
		set.add("you");
		//迭代器遍历
		Iterator<String> it = set.iterator();
		while(it.hasNext()) {
			String str = it.next();
			System.out.println(str);
		}
		System.out.println("======");
		//增强for循环遍历
		for(String str : set) {
			System.out.println(str);
		}
	}

Set接口实现类HashSet

java.util.HashSet 类,实现接口Set

HashSet集合特点:

  • 底层数据结构是哈希表
  • 是由HashMap支持的
    • HashSet集合,所有功能,都是由HashMap提供
  • 无序的集合, 元素存储的顺序和取出的顺序不一致
  • 线程不安全集合,运行速度快
public static void main(String[] args) {
    //Set接口和实现类HashSet创建对象
    Set<String> set = new HashSet<String>();
    set.add("d");
    set.add("c");
    set.add("a");
    set.add("b");
    System.out.println(set);
}

对象的哈希值

Object类是所有类的父类 : Object类里面定义方法

public native int hashCode();
所有类都继承Object, 所有类都拥有此方法.
hashCode() 返回对象的哈希值

直接输出对象 ,调用toString()

看到结果 : 改口, 对象的哈希值 (不要在说地址), 对象的哈希值和内存地址无关!!

对象的哈希值 : 理解为通过某种计算方法得到的一个 , 十进制数字而已

 public  int hashCode() {
	return 9527;
 }

子类Person,重写了方法hashCode() 自定义自己的哈希值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TxbesXO6-1595421932882)(images/哈希值.jpg)]

字符串对象的哈希值

String类继承Object,重写了父类的方法 hashCode()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZX6D5AMA-1595421932886)(images/String对象自定义的哈希值.jpg)]

哈希计算, *31 目的是为了降低,字符串不同,算出相同哈希值的概率

出现字符串不一样,计算出的哈希值是一样的

哈希表

哈希表数据结构 : Node 节点对象

数组 + 链表组合, HashSet集合,是单向链表,不记录上一个元素是谁

class Node{ 
  E item;
  Node next;
}
哈希表 : private Node[] node ;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zf1zkiL8-1595421932887)(images/哈希表的结构.jpg)]

哈希表存储对象的过程

public static void main(String[] args) {
    Set<String> set = new HashSet<String>();
    set.add("abc");
    set.add("bbc");
    set.add(new String("abc"));
    set.add("重地");
    set.add("通话");
    System.out.println(set);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IcXDplYO-1595421932888)(images/哈希表存储对象的过程.jpg)]

哈希表存储自定义的对象

去掉重复的元素,被存储到哈希表的对象,应该重写hashCode()和equals()方法

public static void main(String[] args) {
    //HashSet集合,存储自定义对象
    Set<Person> set = new HashSet<Person>();

    set.add(new Person("a",11));
    set.add(new Person("b",12));
    set.add(new Person("c",13));
    set.add(new Person("c",13));
    set.add(new Person("d",14));

    System.out.println(set);
}
@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

关于hashCode()和equals()

两个对象的哈希值相等,equals()方法永远返回一个值

两个对象哈希值不等, 但是equals方法返回true

Sun : hashCode协定

  • 一个对象,多次调用hashCode(),结果相同
  • x对象.equals(y对象)=true, x对象的哈希值和y对象的哈希值,必须一致

HashMap源码

  • 初始化哈希表的容量的计算方法

    static final int tableSizeFor(int cap) {
            int n = cap - 1;
            n |= n >>> 1;
            n |= n >>> 2;
            n |= n >>> 4;
            n |= n >>> 8;
            n |= n >>> 16;
            return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
        }
    
    得到我们指定容量,大于他的 8421
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值