Java_4_Lambda_泛型_集合

12 篇文章 1 订阅
订阅专栏

Lambda表达式

Lambda语法

概念:Lambda表达式是生成函数式接口的匿名实现类实例对象的语法糖,可理解为将一段可传输的代码。 Lambda表达式可以看作是一个匿名函数,也可称为闭包。Lambda表达式可以写出更简洁、更灵活的代码,而其作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

表达式成员:lambda形参列表、箭头、lambda方法体

语法:

  1. 无参,无返回值

    Runnable runnable = () -> System.out.println("Runnable");
    
  2. 一参,无返回值

    Consumer<String> c = x -> System.out.println("Consumer");
    
  3. 两参,多语句

    Comparator<Integer> c = (x,y) -> {
    	System.out.println("Comparator");
    	return Integer.compare(x,y);
    }//形参列表数据类型可不写,JVM可自动根据上下文推断
    
  4. 两参,仅有一条返回值语句

    Comparator<Integer> c = (x,y) -> Integer.compare(x,y);
    
函数式接口

概念:仅有一个抽象方法的接口,称之为函数式接口,可通过Lambda表达式语法快速生成函数式接口的匿名内部实现类的实例(即Lambda本质是函数式接口的实例)。函数式接口可用==@FunctionalInterface==注解以此来检查是否定义为函数式接口,并在Javadoc中声明其为函数式接口。java.util.function提供丰富的函数式接口

四大核心接口:

其他接口:

方法引用

原理:当需要传递给Lambda体的操作,已经有实现的方法了,可使用方法引用。方法引用可视为Lambda深层次的表达,方法引用就是Lambda表达式,是函数式接口的实例,通过方法名字来指向一个方法,可以认为Lambda的语法糖

要求:实现接口的抽象方法的参数列表和返回值类型,与方法引用的方法参数列表与返回值类型一致

语法:

  1. 通过对象对象名::实例方法名
  2. 通过类静态方法类名::静态方法名
  3. 通过类成员方法类名::实例方法

实例:

//1.对象::实例方法名
//Consumer中的void accept(T t)
//ps对象的void println(T t)
PrintStream ps = System.out;
Consumer<String> con1 = ps::prinltn;
con1.accept("lxl");//控制台输出lxl

//2,类::静态方法名
//Comparator中的int compare(T t1,T t2)
Interger中的static int compare(T t1,T t2)
Comparator<Integer> com1 = Integer::compare;
com1.compare(12,13);//返回-1

//3.类::实例方法名
//Comparator中的int compare(T t1,T t2)
//String中的int compareTo(T t)
//String的compareTo方法用t1调用,t2为参数,该情况可使用方法引用
Comparator<String> com2 = String::compareTo;
com2.compare("abc","abd");//返回-1

//Function中的R apply(T t)
//Employee类中的String getName()
//Employee的getName方法用t调用,该情况可使用方法引用
Employee emp = new Employee("lxl")Function<Employee,String> fn = Employee::getName;
fn.apply(emp);//返回lxl


//构造器引用
//Employee中的public Employee()构造器
//Supplier<T>中的T get()返回获取Employee对象
Supplier<Employee> sup = new Supplier<Employee>(){//原始写法
    @Override
    public Employee get(){
        return new Employee();
    }
}
Supplier<Employee> sup = () -> new Employee();//Lambda表达式写法
Supplier<Employee> sup = Employee::new;//构造器引用写法

//Employee中的public Employee(String name)构造器
//Function<T,R>中的R apply(T t)返回获取Employee对象
Function<String,Employee> fn = Employee::new;
//此时fn的Employee apply方法参数列表为String t,对应Employee(String name)构造器

//Employee中的public Employee(int id,String name)构造器
//BiFunction<T,U,R>中的R apply(T t,U u)返回获取Employee对象
BiFunction<Integer,String,Employee> fn = Employee::new;
//此时fn的Employee apply方法参数列表为Integer t,String u
//对应Employee(int id,String name)构造器


//Lambda表达式写法
Function<Integer,String[]> fn1 = length -> new String[length];
//数组引用写法
Function<Integer,String[]> fn2 = Stirng[] :: new;
//即将数组视为一个特殊的类

泛型

泛型介绍
  1. 泛型又称参数化类型,是JDK5.0出现的新特性,解决数据类型安全性问题
  2. 在类声明和实例化时只需指定好具体类型即可
  3. Java泛型若保证编译时没有发出警告,运行时就不会产生
  4. 泛型的作用是:可在类声明时通过一个标识指定类中某个属性的类型,或是某个方法的返回值类型,或是参数类型
  5. 泛型表示的数据类型,是在类对象定义时指定(即是编译期指定)
  6. 泛型仅仅只是针对编译阶段有效!在运行时期是会被擦除的(类型擦除)
泛型注意事项
1.给泛型指定数据类型,必须是引用类型,不可为基本数据类型
2.给泛型指定具体类型后,可以传入该类型或其子类类型
3.泛型的使用形式:
	(1)ArrayList<Integer> list1 = new ArrayList<Integer>();
	(2)List<Integer> list2 = new ArrayList<Integer>();
	(3)ArrayList<Integer> list1 = new ArrayList<>(); 推荐使用简写
4.若定义类时使用了泛型,但是创建类对象时未传入类型,则泛型的数据类型默认为Object
自定义泛型
自定义泛型类
基本语法:
class 类名<T>{}

注意事项:
1.普通成员可以使用泛型(属性、方法)
2.使用泛型的数组,不能初始化
3.静态方法中不能使用类的泛型
4.泛型类的类型,在创建对象时确定(new 类名<泛型类型>)
5.若泛型无指定类型,默认为Object
-------------------------------------------------------------------------
自定义泛型接口
基本语法:
interface 接口名<T,R>{
	public T get(){};
}

注意事项:
1.接口中静态成员也不能使用泛型
2.泛型接口的类型,可在继承接口或实现接口时确定
3.始终不确定泛型的类型,可直到创建对象时确定泛型的类型	
-------------------------------------------------------------------------
自定义泛型方法
基本语法:
修饰符 <T,R>返回类型 方法名(T t,R r){}

注意细节:
1.泛型方法可以定义在普通类中,也可定义在泛型类中
2.当泛型方法被调用时,类型会确定(编译器根据传入参数确定泛型)
3.public void eat(E e){},不是泛型方法,只是使用了泛型
4.泛型方法可以使用类声明的泛型,也可以使用自己声明的泛型
泛型继承与通配符
  1. 泛型不具有继承性
  2. 泛型<?>支持任意的泛型类型
  3. <? extends A>支持A类及其子类,规定泛型上限
  4. <? super A支持A类及其父类,不限于直接父类,规定泛型下限

集合的使用

集合体系图

Collection接口概述

在这里插入图片描述

Iterator迭代器

在这里插入图片描述

List接口及其实现类

List集合选型:

集合底层结构增删效率查询效率
ArrayList可变数组
LinkedList双向链表
  1. 改查多选ArrayList,增删多选LinkedList
  2. 一般开发情况查询较多,大部分选择ArrayList
  3. 根据业务灵活选择
ArrayList类使用与解析

在这里插入图片描述

常用方法:

public boolean add(E e); // 直接在集合的末尾添加元素数据e
public void add(int index,E e); // 在集合指定index索引位置添加元素数据e 
public E get(int index); // 获得集合总指定index索引位置的元素数据
public E remove(int index); // 删除集合中指定index索引位置的元素数据
public boolean remove(Object obj); // 删除集合中指定的元素数据obj
public E set(int index,E e); // 将集合index索引位置的元素数据修改为e
public int size();  // 获得集合里面元素数据的个数!
public int indexOf(Object o);  //返回o在集合中第一次出现的索引,使用equals比较

集合构造器源码:

public ArrayList(int initialCapacity) {
	if (initialCapacity > 0) {
		this.elementData = new Object[initialCapacity];
 } else if (initialCapacity == 0) {
		this.elementData = EMPTY_ELEMENTDATA;
//private static final Object[] EMPTY_ELEMENTDATA = {};
	} else {
		throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
	}
}

public ArrayList() {
	this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
 //private static final Object[] EMPTY_ELEMENTDATA = {};
}

集合扩容源码:

public boolean add(E e) {
  ensureCapacityInternal(size + 1);
  elementData[size++] = e;
  return true;
}

private void ensureCapacityInternal(int minCapacity) {
	ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));//calculateCapacity中判断是否是第一次扩容
}

private static int calculateCapacity(Object[] elementData, int minCapacity) {
	if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
  //DEFAULTCAPACITY_EMPTY_ELEMENTDATA为fianl空数组
		return Math.max(DEFAULT_CAPACITY, minCapacity);
  //DEFAULT_CAPACITY为10,判断是否是第一次扩容
	}
	return minCapacity;//返回添加后的集合容量
}

private void ensureExplicitCapacity(int minCapacity) {
	modCount++;//记录集合(elementData)修改次数
	if (minCapacity - elementData.length > 0)
  //判断是否需要扩容
		grow(minCapacity);
}
}

private void grow(int minCapacity) {
	int oldCapacity = elementData.length;
	int newCapacity = oldCapacity + (oldCapacity >> 1);
//扩容算法
	if (newCapacity - minCapacity < 0)
  //判断扩容后容量是否满足需求
		newCapacity = minCapacity;
	if (newCapacity - MAX_ARRAY_SIZE > 0)
  //判断扩容后容量是否大于数组类型最大长度
		newCapacity = hugeCapacity(minCapacity);
//实际上的数组扩容
	elementData = Arrays.copyOf(elementData, newCapacity);
}
Vector类使用与解析

概述:

  1. Vector底层是一个Object数组,protected Object[] elementData;
  2. Vector是线程同步(线程安全),Vector类操作方法带有synchronized
  3. 开发中考虑线程安全时,可使用Vector
  4. 无参构造器生成的Vector对象,默认容量为10;有参构造器生成的Vector对象容量为指定大小;之后每次扩容后的大小为原来的2倍

集合扩容源码:

public synchronized boolean add(E e){
    modCount++;//记录该Vector对象修改次数
    ensureCapacityHelper(elementCount+1);
    //elementCount为数组当前使用的容量
    elementData[elementCount++]=e;
    return true;
}
private void ensureCapacityHelper(int minCapacity){
    if(minCapacity - elementDate.length > 0){
        //minCapacity为增加后的数组容量
        grow(minCapacity);//如果需要容量小于数组长度则扩容
    }
} 
public void grow(int minCapacity){
    int oldCapacity = elementData.length;//记录原来数组长度
    int newCapacity = oldCapacity+((capacityIncrement>0)?capacityIncrement:oldCapacity);//capacityIncrement为0,
    if(newCapacity-minCapacity<0){//判断新容量是否小于需要容量
        newCapacity = minCapacity;
    }
    if(newCapacity - MAX_ARRAY_SIZE>0){
        //判断新容量是否大于数组类型最大长度
        newCapacity = hugeCapacity(minCapacity);
    }
    elementData = Arrays.copyOf(elementData,newCapacity);
    //使用Arrays.copyOf实现扩容 
}
LinkedList类使用与解析

在这里插入图片描述

集合添加与删除源码:

public boolean add(E e) {
	linkLast(e);
	return true;
}
void linkLast(E e) {
	final Node<E> l = last;//保存last引用
	final Node<E> newNode = new Node<>(l, e, null);
 //将e对象为参数生成Node类型对象
	last = newNode;//将新Node对象引用给last变量
	if (l == null)
     //如果最初last为null,新Node对象即为第一个数据
		first = newNode;
	else
     //若非第一个,则将上个Node的next属性指向新Node对象
		l.next = newNode;
	size++;//LinkedList大小+1
	modCount++;//记录该LinkedList对象修改次数
}
public E remove() {
	return removeFirst();
}
public E removeFirst() {
	final Node<E> f = first;//f指向first指向的第一个结点
	if (f == null)//若第一个结点为null,抛出异常
		throw new NoSuchElementException();
	return unlinkFirst(f);//第一结点作为参数,调用unlinkFirst
}
private E unlinkFirst(Node<E> f) {
	final E element = f.item;
	final Node<E> next = f.next;//next指向第二结点
	f.item = null;
	f.next = null; 
	first = next; //first指向第一结点的next属性,即第二结点
	if (next == null)//若第二结点为null,则将last也置空
		last = null;//此时集合为空
	else
		next.prev = null;//第二结点的prev属性置空
	size--;//LinkedList大小-1
	modCount++;
	return element;//返回被删除Node的item,即被删的数据
}
Set接口及其实现类

在这里插入图片描述

Set集合选型:

集合是否有序去重规则
HashSet无序hasCode+equals
LinkedHashSet有序(存取一致)同上
TreeSet默认排序/自定义排序元素compareTo/比较器compare
HashSet类使用与解析

在这里插入图片描述

源码解析:

public HashSet(){
	map = new HashMap<>();//底层给map属性赋值一个新HashMap对象
}

public boolean add(E e) {
	return map.put(e, PRESENT)==null;
//PRESENT为静态属性,值为Object对象,用以占HashMap中k-v中v位置
}

public V put(K key, V value) {
	return putVal(hash(key), key, value, false, true);
}

static final int hash(Object key) {
	int h;
	return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
	//获得key的哈希值并处理,算法尽量避免出现相同的哈希值
}

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {
	Node<K,V>[] tab; Node<K,V> p; int n, i;//定义辅助变量
	if ((tab = table) == null || (n = tab.length) == 0)
//table是HashMap中存储结点链表的数组
//该if语句判断table是否为空,为空则进行第一次扩容(16长度)
		n = (tab = resize()).length;        
	//resize方法对table进行扩容
	if ((p = tab[i = (n - 1) & hash]) == null)
  //1.根据key的hash值,计算该key在table表格中的索引
  //2.判断索引的位置是否为空
		tab[i] = newNode(hash, key, value, null);
	//为空则将key作为参数创建Node结点,并将Node结点存储到table中的相应索引的位置
	else {
		Node<K,V> e; K k;
		if (p.hash == hash &&((k == p.key) == key || (key != null && key.equals(k))))
  //判断p指向结点中数据是否与key相同(两个条件):
  //1.p指向结点中hash与被添加的key的hash相同,key与结点中的key属性为同一对象
  //2.key不为空,并调用key的equals与p结点的key比较结果为true
			e = p;
		else if (p instanceof TreeNode)
  //判断 p 是否是红黑树
			e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
		else {//当p指向的数组位置已经是一个链表时进入
			for (int binCount = 0; ; ++binCount) {
      //循环遍历链表
				if ((e = p.next) == null) {//第一循环e指向链表第二元素
         //发现p指向的下一位置为空时,key作为参数创建Node结点,并存储到该位置
					p.next = newNode(hash, key, value, null);
					if (binCount >= TREEIFY_THRESHOLD - 1) 	
             //添加新元素后,判断该链表长度是否大于8
                  treeifyBin(tab, hash);
              	//treeifyBin判断是否满足条件,满足时先table扩容,再将链表转为红黑树
					break;
				}
				if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))
         //发现被添加元素与链表中元素相同时,退出循环
					break;
				p = e;//将p指向后一个Node结点,准备下次循环
			} 
		}
		if (e != null) { 
  //e不为null,就说明元素没有添加成功
			V oldValue = e.value;//e.value是默认的空对象PRESENT
			if (!onlyIfAbsent || oldValue == null)
				e.value = value;
			afterNodeAccess(e);
  	HashMap中该方法为空,由HashMap子类实现并进行业务逻辑
			return oldValue;
		}
	}
	++modCount; //修改次数+1
	if (++size > threshold)
//HashMap的大小+1,并将新大小与临界值进行比较
		resize();
	//若增加元素后的HashMap大小比临界值大,则进行table扩容
	afterNodeInsertion(evict);
//HashMap中该方法为空,由HashMap子类实现并进行业务逻辑
	return null;
}
LinkedHashSet类使用与解析

在这里插入图片描述

源码解读:

static class Entry<K,V> extends HashMap.Node<K,V> {
	Entry<K,V> before, after;//用来存储上个结点,下个结点的地址
	Entry(int hash, K key, V value, Node<K,V> next) {
		super(hash, key, value, next);
	}
}

public LinkedHashSet() {//无参构造器,初始化
	super(16, .75f, true);
}
//上层调用父类的构造器
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
	map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
TreeSet类

原理概述:

  1. TreeSet底层是TreeMap,以红黑树的结构对数据进行存储,查询较快
  2. 若使用无参构造器创建TreeSet,是默认调用元素的compareTo方法进行排序
  3. 使用匿名内部类形式new Comparator(){}作为参数创建TreeSet集合后,可以通过比较器的compare方法中定义排序规则
  4. 不能添加null值

源码解读:

//1.TreeSet构造器将传入的Comparator对象,赋给底层TreeMap的comparator属性
public TreeSet(Comparator<? super E> comparator) {
	this(new TreeMap<>(comparator));
}
public TreeMap(Comparator<? super K> comparator) {
	this.comparator = comparator;
}

//2.调用add时,底层会执行
if (cpr != null) {
	do {
		parent = t;//t为树的根节点
		cmp = cpr.compare(key, t.key);//用传入的比较器进行比较
		if (cmp < 0)
          t = t.left;
      else if (cmp > 0)
          t = t.right;
      else//若出现相同元素,退出并setValue替换值
          return t.setValue(value);
   } while (t != null);
}
Map接口及其实现类

Map集合遍历方法:

Map map = new HashMap();

//第一组:先取出所有的key,通过key得到value
Set keyset = map.keySet();
//第一种方法:增强for
for (Object key : keyset) {
 System.out.println(map.get(key));
}
//第二种:迭代器
Iterator iterator1 = keyset.iterator();
while (iterator1.hasNext()) {
 Object key = iterator1.next();
 System.out.println(map.get(key));
}

//第二组:直接把所有的values取出
Collection values = map.values();
//第一种:增强for
for (Object value : values) {
 System.out.println(value);
}
//第二种:迭代器
Iterator iterator2 = values.iterator();
while (iterator2.hasNext()) {
 Object value = iterator2.next();
 System.out.println(value);
}

//第三组:通过EntrySet获取K-V
Set entryset = map.entrySet();
//第一种:增强for
for (Object entry : entryset) {
 //将Object类型的entry转成Map.Entry类型
 //entry实际运行类型是HashMap$Node
 Map.Entry m = (Map.Entry) entry;
 System.out.println(m.getKey()+"-"+m.getValue());
}
//第二种:迭代器
Iterator iterator3 = entryset.iterator();
while (iterator3.hasNext()) {
 Map.Entry m  = (Map.Entry)iterator3.next();
 //iterator3.next()返回的是HashMap$Node类型
 System.out.println(m.getKey()+"-"+m.getValue());
}
//猜想:不可以使用HashMap.Node的原因是:Node静态成员内部类权限修饰符为默认,而Map.Entry为Map接口中内部接口,接口中的方法都是默认public  abstract修饰且必须为public;接口中的属性都是默认public static final修饰
HashMap类使用与解析

注意事项:

  1. HashMap是Map接口使用频率最高的实现类,K-V对的方式存储数据
  2. Key可为且仅有一个null,不能复用;但Value可重复,允许null键值
  3. 若添加相同key,会覆盖原来的value,等同修改
  4. 与HashSet一样,不保证映射顺序,因其底层为hash表实现存储(数组+链表+红黑树)
  5. 无实现同步,非线程安全,需要线程安全的情况下可以使用ConcurrentHashMap
  6. 扩容机制与HashSet一致,因为其底层就是HashMap,源码可参照HashSet部分

Hashtable类使用与解析

源码分析:

//1.底层由数组Hashtable$Entry[],初始化为11
private transient Entry<?,?>[] table;
public Hashtable() {
	this(11, 0.75f);//无参初始化table长度为11
}

//2.临界值threshold = initialCapacity * 0.75
//initialCapacity为扩容时新数组长度

private void addEntry(int hash, K key, V value, int index) {
	modCount++;
	Entry<?,?> tab[] = table;
//3.扩容:当Hashtable元素个数大于等于临界值会触发扩容,扩容大小为2n+1
	if (count >= threshold) {//count为table数组中元素总数
		rehash();
		tab = table;
		hash = key.hashCode();
		index = (hash & 0x7FFFFFFF) % tab.length;
	}
	@SuppressWarnings("unchecked")
	Entry<K,V> e = (Entry<K,V>) tab[index];
//4.将key,value封装成Hashtable$Entry类型的结点放入table中
	tab[index] = new Entry<>(hash, key, value, e);
	count++;
}

protected void rehash() {
	int oldCapacity = table.length;
	Entry<?,?>[] oldMap = table;
	int newCapacity = (oldCapacity << 1) + 1;//扩容大小为2n+1
	if (newCapacity - MAX_ARRAY_SIZE > 0) {
		if (oldCapacity == MAX_ARRAY_SIZE)
			return;
		newCapacity = MAX_ARRAY_SIZE;
	}
	Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
	modCount++;//table表被修改次数+1
	threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);//生成新的临界值
	table = newMap;
	for (int i = oldCapacity ; i-- > 0 ;) {
		for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
			Entry<K,V> e = old;
			old = old.next;
			int index = (e.hash & 0x7FFFFFFF) % newCapacity;
			e.next = (Entry<K,V>)newMap[index];
			newMap[index] = e;
		}
	}
}
Properties类使用与解析

基本介绍:

  1. Properties类继承于Hashtable并实现了Map接口,也使用一种键值对形式保存数据,使用特点与Hashtable类似
  2. Properties还可从properites文件中,加载数据到Properties类对象并进行读取和修改
  3. 工作中常作为配置文件读取后存储的数据集合

使用方法:

  • getProperty(String key)用指定的键在此属性列表中搜索属性。也就是通过参数 key ,得到 key 所对应的 value。
  • load(InputStream inStream)从输入流中读取属性列表(键和元素对),通过对指定的文件(比如说上面的test.properties 文件)进行装载
  • setProperty(String key,String value)调用Hashtable的方法 put,他通过调用基类的put方法来设置键值对。
  • store(OutputStream out,String comments)以与写入相同的格式,将此Properties表中的属性列表(键值对)写入到指定的文件中去。
  • clear()清除此Properties表所有装载的键值对。
TreeMap类使用与解析

原理概述:

  1. TreeMap底层以红黑树的结构对数据进行存储,查询较快
  2. 若使用无参构造器创建TreeSet,是默认调用元素的compareTo方法进行排序
  3. 使用匿名内部类形式new Comparator(){}作为参数创建TreeSet集合后,可以通过比较器的compare方法中定义排序规则
  4. key不可为null

源码分析:

//1.将传入的实现Comparator接口的匿名内部类,传给TreeMap类中的comparator
public TreeMap(Comparator<? super K> comparator) {
	this.comparator = comparator;
}

//2.第一次使用put方法添加
if (t == null) {
	compare(key, key); //检测key是否为null
	root = new Entry<>(key, value, null);
  size = 1;
  modCount++;
  return null;
}
Collections工具类与接口方法

在这里插入图片描述

在这里插入图片描述

各接口集合选型
  1. 判断存储的类型:(1)一组对象 (2)一组键值对

  2. 一组对象/单列:Collection接口
    允许重复:List接口
    增删多:LinkedList(双向链表)
    改查多:ArrayList(Object类型可变数组),Vector(线程安全)
    不允许重复:Set
    无序:HashSet(底层HashMap)
    排序:TreeSet
    插入与取出顺序一致:LinkedHashSet(底层LinkedHashMap)

  3. 一组键值对:Map
    键无序:HashMap(哈希表(数组+链表+红黑树))
    键排序:TreeMap
    键插入与取出顺序一致:LinkedHashMap(数组+双向链表)
    读取文件:Properties(继承Hashtable)

不可变集合

概述:不可变集合,就是不可被修改的集合。集合的数据项在创建的时候提供,并且在整个生命周期中都不可改变。否则报错。JDK9开始支持!!!

引用场景:如果某个数据不能被修改,把它防御性地拷贝到不可变集合中是个很好的实践。或者当集合对象被不可信的库调用时,不可变形式是安全的。

使用方法:

在List、Set、Map接口中,都存在of方法,可以创建一个不可变的集合。

这个集合不能添加,不能删除,不能修改。

方法名称说明
static List of(E…elements)创建一个具有指定元素的List集合对象
static Set of(E…elements)创建一个具有指定元素的Set集合对象
static <K , V> Map<K,V> of(E…elements)创建一个具有指定元素的Map集合对象
泛型Lambda,如此强大!
编程与实战的博客
01-17 985
最近发现泛型编程有了另一利器——泛型Lambda,比想象当中要强大许多,威力不小,和大家分享一下。本篇内容需要对泛型编程有所了解,若是读过之前更新的相关文章,食用更佳。1泛型编程开始之前,...
Java8中lambda表达式的应用及一些泛型相关知识
08-31
主要介绍了Java8中lambda表达式的应用及一些泛型相关知识的相关资料
Java中获取lambda表达式的泛型类型
byx的博客
12-12 1446
假设有以下接口: public interface Factory<T> { T create(); } 这是一个泛型接口,在实现Factory的时候需要指定泛型参数: public class StringFactory implements Factory<String> { @Override public String create() { return "hello"; } } public class IntegerFa
java8中lambda表达式的应用,以及一些泛型相关
weixin_30641465的博客
01-03 993
语法部分就不写了,我们直接抛出一个实际问题,看看java8的这些新特性究竟能给我们带来哪些便利 顺带用到一些泛型编程,一切都是为了简化代码 场景: 一个数据类,用于记录职工信息 public class Employee { public String name; public int age; public char sex; pu...
Java Lambda表达式如何支持泛型
m0_60521228的博客
03-11 1392
你可以在Lambda表达式之外定义一个泛型类或方法,并在Lambda表达式中使用这个泛型类型。// 泛型类 public static class Box < T > {// 创建泛型类的实例 Box < String > stringBox = new Box < >("Hello, World!");
java_base1_lang.rar_java_base1_lang ppt
09-19
14. ** Lambda表达式**:Java 8引入的新特性,简化了匿名内部类的写法,提高了代码的简洁性和可读性。 15. **Stream API**:Java 8新加入的处理集合的API,提供了一种更流畅、函数式的编程风格。 以上这些知识点...
java_PPT.rar_JAVA P_java .ppt_java ppt_java.ppt_javapot
09-22
4. **集合框架**:Java集合框架是存储和管理对象的重要工具,PPT可能详细解释了ArrayList、LinkedList、HashSet、HashMap等容器的使用。 5. **IO流**:Java的输入输出系统非常强大,PPT可能会介绍不同类型的流,如...
Java_jihe.rar_java集合
09-20
6. 泛型Java集合框架广泛使用泛型,确保了类型安全,避免了强制类型转换,提高了代码可读性和健壮性。 7. 集合操作:包括添加元素(add),删除元素(remove),检查元素是否存在(contains),以及各种转换和复制操作...
Java_go_over.rar_Go_ Go_ Go!_java go over_javaover
09-21
5. **集合框架篇**:ArrayList、LinkedList、HashSet、HashMap等集合类的使用,以及泛型、迭代器和比较器的概念。 6. **IO流篇**:输入输出流的分类,字符流与字节流的区别,缓冲流的使用,以及文件操作和对象序列化...
java_100_example.rar_java eclipse example
09-24
12. **Lambda表达式**:Java 8引入的新特性,简化函数式编程,处理集合操作。 13. **Stream API**:Java 8中的新特性,用于处理集合,提供了并行流和串行流。 14. **注解(Annotation)**:用于元编程,可以为...
Java基础05—泛型Lambda表达式
spark2010的博客
03-07 2254
本文是学习Java时所记录的学习笔记,本节包含了泛型Lambda表达式的介绍。
JAVA 学习 面试(九)Lambda表达式与泛型
qq_42767993的博客
01-25 1010
泛型方法,是在调用方法的时候指明泛型的具体类型 ,当在一个方法签名中的返回值前面声明了一个 < T > 时,该方法就被声明为一个泛型方法。是一种特殊的泛型类型,用于限定泛型类型参数的范围,在java中,数组是可以协变的,比如dog extends Animal,那么Animal[] 与dog[]是兼容的。>,无边界的通配符的主要作用就是让泛型能够接受未知类型的数据.函数式接口只定义了唯一的抽象方法的接口(除了隐含的Object对象的公共方法),若增加新的方法,就非函数式接口,编译会失败。
java学习(8)(Lambda表达式,泛型集合
最新发布
2201_75508405的博客
05-12 1910
Lambda表达式,泛型集合
Java泛型、反射、注解、Lambda表达式
Shingle_的博客
08-22 1073
泛型介绍 (使用频率高) 泛型类型是通过类型参数化的泛型类或接口。通过类型参数化,来解决程序的通用性设计和实现的若干问题。 泛型试图解决的问题: 编译期类型检查:可以避免运行时错误的发生 强制类型检查 可读性和灵活性 泛型本身就是对于继承在使用上的一种增强。编译器在编译源码时,首先进行泛型类型参数的检查,然后进行类型 擦除并同时在类型参数出现的位置插入强制类型转换指令从而实现。 ...
泛型lambda表达式
fpcc的专栏
12-28 831
泛型lambda表达式及应用进行分析说明
C++14 泛型lambda
程序员Link
12-15 1042
lambda的参数列表中可以使用auto。 // 执行 g++ -c -std=c++11 generic_lambdas.cpp 通过 auto f = [](int a) {std::cout << a << std::endl;}; // 执行 g++ -c -std=c++11 generic_lambdas.cpp 报错 // generic_lambdas.cpp:7:13: error: 'auto' not allowed in lambda parame.
Java中级(二)泛型Lambda、多线程
Apiao9的博客
11-16 332
Java中级总结
JAVA8新特性--lambda表达式结合泛型的简单应用
m0_43514502的博客
07-12 5383
JAVA8新特性–lambda表达式结合泛型的简单应用 本篇文章将介绍小编对java8新特性–lambda表达式的理解,以及java5后引入的泛型的理解。随后介绍将lambda表达式结合泛型的实践。 lambda表达式 小编查阅了很多博客,总结一下: 1、lambda表达式最初java并不会支持,其实现形式与C++的指针相似; 2、java8之前的版本采用匿名内部类来代替lambda表达式; 知识...
C++学习笔记【泛型算法——lambda表达式】
MsMs_的博客
03-04 513
在介绍lambda之前,先介绍下C++中的谓词。谓词是一个可调用的表达式,返回结果是一个能用做条件的值。标准库算法使用的谓词有两类:一元谓词(只接受单一参数)和二元谓词(有两个参数)。接受二元谓词的sort算法用该谓词来代替
写文章

热门文章

  • 启动 Jar 时命令行参数 [-D] 和 [–] 的区别 2551
  • 基于 Docker 部署 Mysql 的时区设置解决方案 2416
  • 延迟队列的三种实现方案 2270
  • Docker_安装使用_容器镜像_Docker-compose_常用指令_网络配置 2109
  • 原生ajax_axios框架_json传输字符串 1136

分类专栏

  • Spring 9篇
  • Lombok 2篇
  • Linux 2篇
  • Docker 3篇
  • MySQL 3篇
  • Nginx 1篇
  • Java 12篇
  • Maven 2篇
  • MyBatis 3篇
  • ajax/json 1篇
  • XML 1篇

最新评论

  • Java_1_基础语法

    CSDN-Ada助手: Java 技能树或许可以帮到你:https://edu.csdn.net/skill/java?utm_source=AI_act_java

最新文章

  • SpringMvc 与 Lombok 碰撞导致 JSON 反序列化失败
  • OpenFeign 个性化_注解配置_日志_请求拦截_请求透传_FastJson解析
  • 基于 Docker_redis6.0.8 实现 Redis 集群扩缩容
2023年22篇
2022年20篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

玻璃钢生产厂家商场冬季美陈的目的户外玻璃钢雕塑一般多少钱湖南仿铜玻璃钢雕塑制作浙江玻璃钢花盆供应达州动物玻璃钢雕塑摆件国内打造浙江省玻璃钢雕塑深圳常见商场美陈厂家直销四川水果玻璃钢雕塑供应商五河玻璃钢花盆花器连江玻璃钢雕塑公司宜春户外玻璃钢雕塑科幻类机甲雕塑玻璃钢多少钱玻璃钢雕塑老黄牛门头沟区商场圣诞美陈布置河南家用玻璃钢雕塑摆件雕塑玻璃钢雕塑定制福建商场美陈有哪些玻璃钢孔子雕塑哪家好仿真玻璃钢雕塑价格开远市玻璃钢雕塑定制云南玻璃钢雕塑厂家直销西安玻璃钢雕塑文化玻璃钢喜羊羊与灰太狼雕塑镇江十一商场美陈西安市玻璃钢雕塑铜陵玻璃钢雕塑制作厂家潮州喷泉雕塑玻璃钢深圳定制玻璃钢雕塑卡通鲸鱼玻璃钢雕塑河南玻璃钢雕塑厂商香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化