1.1 排序
1.1.1 Comparable
比较器有两种 : 1 元素自身比较器, 2 比较器类
思考 : 为什么字符串,Integer,Date可以排序?
因为都实现了 implements Comparable
因为使用treeSet在进行数据添加的时候,会自动调用该对象的compareTo()方法和集合内元素进行比较
如果我们想要存储自定义类型怎么办?
需要实现该接口才行
添加的时候 会自动调用该对象的compareTo方法,而该方法就在Comparable接口中,所以 必须要实现,否则不能添加到TreeSet中
1.1.2 Comparator
treeSet添加的元素必须排序
两种方式 :
1 要添加的元素对应的类实现java.lang.Comparable接口,并实现compareTo方法
2 使用java.util.Comparator比较器类
如果要添加的元素,符合两种比较器(都有) 则 Comparator优先(compare方法)
Comparable : 要添加的元素,实现该接口并覆写compareTo方法
Comparator : 比较器类,常应用 : 比如Integer默认升序,我想降序怎么办? 使用Comparator进行降序排序
如果 添加的元素的类 是我们写的,我们应该使用 Comparable , 因为对扩展开发,其他人还可以使用 Comparator 实现新的排序功能
如果 添加的元素的类 不是我们写的
1 该类有排序(实现了Comparable) 比如Integer,但是 默认排序结果不是我们想要的,那么我们可以使用Comparator进行调整排序,因为优先级高
2 如果该类没有实现排序(没有实现Comparable), 这时候我们需要使用Comparator进行排序,因为我们不可能去改变人家类的源码
package com.demo._Collection;
import java.util.Comparator;
import java.util.TreeSet;
/**
* treeSet添加的元素必须排序
*
* 两种方式 :
* 1 要添加的元素对应的类实现java.lang.Comparable接口,并实现compareTo方法
*
* 2 使用java.util.Comparator比较器类
*
* 如果要添加的元素,符合两种比较器(都有) 则 Comparator优先(compare方法)
*
* Comparable : 要添加的元素,实现该接口并覆写compareTo方法
*
* Comparator : 比较器类,常应用 : 比如Integer默认升序,我想降序怎么办? 使用Comparator进行降序排序
*
* 如果 添加的元素的类 是我们写的,我们应该使用 Comparable , 因为对扩展开发,其他人还可以使用 Comparator 实现新的排序功能
*
* 如果 添加的元素的类 不是我们写的
* 1 该类有排序(实现了Comparable) 比如Integer,但是 默认排序结果不是我们想要的,那么我们可以使用Comparator进行调整排序,因为优先级高
* 2 如果该类没有实现排序(没有实现Comparable), 这时候我们需要使用Comparator进行排序,因为我们不可能去改变人家类的源码
*
*/
public class Collection_10_Sort {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
// TreeSet treeSet = new TreeSet(new SortTest());
TreeSet treeSet = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return i2-i1;
}
});
treeSet.add(1);
treeSet.add(12);
treeSet.add(11);
treeSet.add(3);
treeSet.add(5);
for (Object object : treeSet) {
System.out.println(object);
}
}
}
class SortTest implements Comparator{
@Override
public int compare(Object o1, Object o2) {
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return i2-i1;//降序
}
}
package com.demo._Collection;
import java.util.Comparator;
import java.util.TreeSet;
public class Collection_11_Sort {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
TreeSet treeSet = new TreeSet(new Comparator() {//匿名内部类
@Override
public int compare(Object o1, Object o2) {
Student s1 = (Student) o1;
Student s2 = (Student) o2;
//先比较id,再比较年龄
if (s1.getId() < s2.getId()) {
return -1;
}else if (s1.getId() > s2.getId()) {
return 1;
}else{
return s1.getAge() - s2.getAge();
}
}
});
treeSet.add(new Student(1, 19, "张三1"));
treeSet.add(new Student(2, 18, "张三2"));
treeSet.add(new Student(3, 16, "张三3"));
treeSet.add(new Student(3, 13, "张三4"));
treeSet.add(new Student(3, 18, "张三5"));
for (Object object : treeSet) {
System.out.println(object);
}
}
}
class Student{
private int id;
private int age ;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [id=" + id + ", age=" + age + ", name=" + name + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(int id, int age, String name) {
super();
this.id = id;
this.age = age;
this.name = name;
}
}
1.1.3 Collections
List排序,想要排序 元素必须实现 Comparable接口
package com.demo._Collection;
import java.util.ArrayList;
import java.util.Collections;
/**
* List排序,想要排序 元素必须实现 Comparable接口
*/
public class Collection_12_Sort {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add(2);
arrayList.add(22);
arrayList.add(12);
arrayList.add(5);
// 可以使用这个方法 是因为 Integer 中 实现了 Comparable接口
Collections.sort(arrayList);
System.out.println(arrayList);
}
}
如果 自身 的Comparable实现的排序方式,不是我们想要的,或者 没有实现Comparable排序
package com.demo._Collection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/**
* 如果 自身 的Comparable实现的排序方式,不是我们想要的,或者 没有实现Comparable排序
*
* 那么我们应该如何对list排序呢?
*
* Comparator
*/
public class Collection_13_Sort {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add(2);
arrayList.add(22);
arrayList.add(12);
arrayList.add(5);
Collections.sort(arrayList,new Comparator() {//不能用自己的类去写,只能够重新定义一个排序类或者匿名内部类。
@Override
public int compare(Object o1, Object o2) {
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return i2-i1;//降序
}
});
System.out.println(arrayList);
}
}
1.1.4 总结
如果 添加的元素的类 是我们写的,我们应该使用 Comparable , 因为对扩展开发,其他人还可以使用 Comparator 实现新的排序功能
如果 添加的元素的类 不是我们写的
1 该类有排序(实现了Comparable) 比如Integer,但是 默认排序结果不是我们想要的,那么我们可以使用Comparator进行调整排序,因为优先级高
2 如果该类没有实现排序(没有实现Comparable), 这时候我们需要使用Comparator进行排序,因为我们不可能去改变人家类的源码
1.2 Set
1.2.1 TreeSet
TreeSet : 元素必须有序,添加的元素会按照某种规则自动排序
想要使用TreeSet,元素必须要排序
数字 : 默认从小到大
字符串 : 默认比较每位ASCII码
日期 : 默认比较自然日期 昨天-今天-明天
1.2.2 HashSet
1.2.2.1 散列表
hash算法 : 是一种安全的加密算法,把不定长的值改变为定长值,并不能保证唯一性
散列表 :
数组中 保存链表(单向链表),并且链表节点内有四个属性
1 key 2 value 3 next 4 hash
散列表是一种数据结构,不过java中屏蔽了,直接以封装的形式封装到了HashSet, HashMap 和HashTable中
其中hashTable已经过时
hash算法在java中 就是指 hashCode函数及重写
哈希的目的 就是为了查询快,因为hash是一个固定的值
1 hash过程
拿到对象,调用对象自身的hashCode()方法,然后进行hash算法,得到数组下标,把值保存到对应的数组中,
Set特性 : 无序 , 不可重复(hashCode和equals)
2 HashSet 和 HashMap
HashSet 就是HashMap的封装,本质就是一个HashMap
默认初始化容量 都是 16
封装之后 HashSet把value值屏蔽了,只能操作key,所以在使用set添加的时候,只需要传入key即可
3 添加过程
1 使用添加的键值对中的key,调用key的hashCode方法,生成hash值,进行hash算法得到数组下标
,判断该下标上是否有元素,如果没有,把该键值对 保存到该数组中即可
2 如果该数组中有对象,则调用key的equals方法和数组中的元素进行比较,如果相等则key不添加,value值覆盖
3 如果不相等,就把该 对象的 添加到已有元素的next属性,形成链表
4 如果添加的时候 就已经是链表了,则需要用key和链表中所有的元素key进行比较是否相等
1.2.2.2 HashSet 使用
因为散列表中 需要使用hashCode和equals来表示对象的唯一性
所以 在进行添加自定义类型的时候,需要考虑 按需求重新hashCode和equals方法
package com.demo._Collection;
import java.util.HashSet;
import java.util.Set;
/**
* hash算法 : 是一种安全的加密算法,把不定长的值改变为定长值,并不能保证唯一性
*
* 散列表 :
* 数组中 保存链表(单向链表),并且链表节点内有四个属性
* 1 key 2 value 3 next 4 hash
*
* 散列表是一种数据结构,不过java中屏蔽了,直接以封装的形式封装到了HashSet, HashMap 和HashTable中
* 其中hashTable已经过时
*
* hash算法在java中 就是指 hashCode函数及重写
*
* 哈希的目的 就是为了查询快,因为hash是一个固定的值
*
* 1 hash过程
* 拿到对象,调用对象自身的hashCode()方法,然后进行hash算法,得到数组下标,把值保存到对应的数组中,
*
* Set特性 : 无序 , 不可重复(hashCode和equals)
*
* 2 HashSet 和 HashMap
* HashSet 就是HashMap的封装,本质就是一个HashMap
* 默认初始化容量 都是 16
* 封装之后 HashSet把value值屏蔽了,只能操作key,所以在使用set添加的时候,只需要传入key即可
*
* 3 添加过程
* 1 使用添加的键值对中的key,调用key的hashCode方法,生成hash值,进行hash算法得到数组下标
* ,判断该下标上是否有元素,如果没有,把该键值对 保存到该数组中即可
* 2 如果该数组中有对象,则调用key的equals方法和数组中的元素进行比较,如果相等则key不添加,value值覆盖
* 3 如果不相等,就把该 对象的 添加到已有元素的next属性,形成链表
* 4 如果添加的时候 就已经是链表了,则需要用key和链表中所有的元素key进行比较是否相等
*
* 因为散列表中 需要使用hashCode和equals来表示对象的唯一性
* 所以 在进行添加自定义类型的时候,需要考虑 按需求重新hashCode和equals方法
*
*/
public class Collection_14_HashSet {
public static void main(String[] args) {
Set set = new HashSet();
set.add(2);
set.add(44);
set.add("xxx");
set.add("xxx");//只能够添加一种,唯一性
for (Object object : set) {
System.out.println(object);//打印出的顺序不一样,因为对添加的数据进行hash值算法,地址是不一样的
}
}
}
package com.demo._Collection;
import java.util.HashSet;
import java.util.Set;
public class Collection_15_HashSet {
@SuppressWarnings(“unchecked”)
public static void main(String[] args) {
Set set = new HashSet();
set.add(new Employee(“1”, “张三1”));
set.add(new Employee(“2”, “张三”));
set.add(new Employee(“3”, “张三”));
set.add(new Employee(“1”, “张三2”));
for (Object object : set) {
System.out.println(object);
}
}
}
class Employee {
private String no;
private String name;
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Employee(String no, String name) {
super();
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "Employee [no=" + no + ", name=" + name + "]";
}
@Override
public int hashCode() {
System.out.println("hashCode执行了");
return no.hashCode();
}
@Override
public boolean equals(Object obj) {
System.out.println("equals执行了");
if (this == obj) {
return true;
}
if (obj instanceof Employee) {
Employee e = (Employee)obj;
if (no.equals(e.no)) {
return true;
}
}
return false;
}
}
2.1 概述
Map : 无序 可重复
value可重复, key不可重复
Map和 集合的操作 基本都是一样的
Object put(Object key,Object value) : 向map中添加键值对
void clear() : 清空
int size() : 添加个数
boolean isEmpty() : 判断是否为空
Object get(Object key) : 根据key 获取value
Collection values() : 获取map中的所有value值,以集合形式返回
booelan containsKey(Object key) : 判断是否包含某个key
booelan containsValue(Object value) : 判断是否包含某个value
Set keySet() : 获取map中的所有key,以Set集合形式返回
Set entrySet() : 返回map中的键值对映射(key=value),以Set集合形式返回
V remove(Object key) : 根据key删除指定映射关系,返回value值
map不能直接遍历,可以通过keySet 等方法进行间接遍历
Map用于保存具有映射关系的数据,因此Map集合里保存两组值。
2.2 常用方法
2.3 HashMap
package com.demo._Map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Map : 无序 可重复
* value可重复, key不可重复
*
* Map和 集合的操作 基本都是一样的
*
* Object put(Object key,Object value) : 向map中添加键值对
* void clear() : 清空
* int size() : 添加个数
* boolean isEmpty() : 判断是否为空
* Object get(Object key) : 根据key 获取value
*
* Collection values() : 获取map中的所有value值,以集合形式返回
* booelan containsKey(Object key) : 判断是否包含某个key
* booelan containsValue(Object value) : 判断是否包含某个value
*
* Set keySet() : 获取map中的所有key,以Set集合形式返回
* Set entrySet() : 返回map中的键值对映射(key=value),以Set集合形式返回
*
* V remove(Object key) : 根据key删除指定映射关系,返回value值
*
* map不能直接遍历,可以通过keySet 等方法进行间接遍历
*/
public class Map_01 {
public static void main(String[] args) {
Map map = new HashMap();
//存储跟json一样{"A":"one","B":"two"}
map.put("A", "one");
map.put("B", "two");
map.put("C", "three");
map.put(1003, "rose");
map.put('A', 1000);
map.put(65, 1000);
map.put("'A'", 1000);
map.put("A", 3000);
// 支持 key和 value 都是null,但是没什么意义,并且只能有一个key为null
map.put(null, null);
// 8
System.out.println(map.size());
// 调用"1003"的hashCode值,然后进行hash 得到数组下标
// 用该对象调用equals方法,和数组中链表的所有对象的key进行比较
// 此对象为 字符串1003 而 map中 没有,只有一个Integer的1003
// false
System.out.println(map.containsKey("1003"));
// 只能去挨个遍历比较
// true
System.out.println(map.containsValue("rose"));
// 先根据"C" 调用HashCode 然后进行hash,得到数组下标,挨个和链表中对象进行equals比较
// 找到对应的对象后,获取其value值
// three
System.out.println(map.get("C"));
System.out.println("========");
// 获取所有的value 并遍历
Collection c = map.values();
for (Object object : c) {
System.out.println(object);
}
// 根据key,删除指定键值对,并返回value值
// three
System.out.println(map.remove("C"));
System.out.println("------------------");
// 把map中所有的key取出,返回set
Set keys = map.keySet();
for (Object key : keys) {
System.out.println(key+" : "+map.get(key));
}
System.out.println("====");
// 把键值对封装到entry中并以set形式返回
Set entrys = map.entrySet();
for (Object object : entrys) {
// 转换为Entry类型
Entry entry = (Entry) object;
System.out.println(entry.getKey()+" : "+entry.getValue());
}
}
}
2.4 扩展之Properties
特殊的Map : 强制规定键和值都必须是字符串
java.util.Properties
package com.demo._Map;
import java.util.Properties;
/**
* 特殊的Map : 强制规定键和值都必须是字符串
*
* java.util.Properties
*/
public class Map_02 {
public static void main(String[] args) {
Properties p = new Properties();
p.setProperty("driver", "xxx");
p.setProperty("username", "root");
String driver = p.getProperty("driver");
System.out.println(driver);
// 可以传递两个参数,第二个参数是默认值,
// 如果根据password是这个key能够找到对应的value,就取对应的value
// 如果找不到,map中没有password这个key 那么 就返回 admin
System.out.println(p.getProperty("username","admin"));
/** public String getProperty(String key, String defaultValue) {
String val = getProperty(key);
return (val == null) ? defaultValue : val;
}*/
}
}
2.5 SortedMap
SortedMap是接口,子实现了是TreeMap,元素必须有序,会按照某个规定进行排序
实现排序的原因 :
1 被添加的元素,实现了Comparable接口
2 按照需求,编写一个比较器类,该比较器类必须实现Comparator接口
package com.demo._Map;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeMap;
/**
* SortedMap是接口,子实现了是TreeMap,元素必须有序,会按照某个规定进行排序
*
* 实现排序的原因 :
* 1 被添加的元素,实现了Comparable接口
* 2 按照需求,编写一个比较器类,该比较器类必须实现Comparator接口
*/
public class Map_03_SortedMap {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
TreeMap map = new TreeMap();
// 因为Integer实现了Comparable接口,默认升序
// map.put(1, 2);
// map.put(12, 2);
// map.put(13, 2);
// map.put(5, 2);
// 更改 为降序 使用Comparator编写匿名内部类
map = new TreeMap(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return i2-i1;
}
});
map.put(1, 2);
map.put(12, 2);
map.put(13, 2);
map.put(5, 2);
Set keys = map.keySet();
for (Object object : keys) {
System.out.println(object +" : "+map.get(object));
}
}
}
treeMap是靠 compareTo方法决定是否唯一,而 get()方法 是根据key调用compareTo方法和每个key进行比较,返回0,说明相等,就获取value
package com.demo._Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* 使用Comparable实现
*/
public class Map_04_SortedMap {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
SortedMap map = new TreeMap();
Product p1 = new Product("大白菜", 3.5);
Product p2 = new Product("大葱", 8.0);
Product p3 = new Product("土豆", 2.2);
// key表示商品 value表示购买数量
map.put(p1, 3);
map.put(p2, 3);
map.put(p3, 1);
Set keys = map.keySet();
for (Object key : keys) {
int value = (Integer) map.get(key);
Product product = (Product) key;
String name = product.getName();
double price = product.getPrice();
System.out.println(name +"/"+price+" 每kg"+ " , 购买了 " + value+" kg , 共 : "+(price*value)+"元 ");
}
}
}
class Product implements Comparable {
private String name;
private double price;
@Override
public String toString() {
return "Product [name=" + name + ", price=" + price + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Product(String name, double price) {
super();
this.name = name;
this.price = price;
}
@Override
public int compareTo(Object o) {
Product p = (Product) o;
if (price > p.price) {
return 1;
}else if (price < p.price) {
return -1;
}else{
// treeMap是靠 compareTo方法决定是否唯一,而 get()方法 是根据key调用compareTo方法和每个key进行比较,返回0,说明相等,就获取value
return 0;
}
}
}
3. 泛型
3.1 概述
类型检查 : 编译过程中,检查数据类型是否匹配
什么是泛型 : 集合就跟数组一样,都是只能放同一种数据类型的,那么为什么集合中什么都能放呢?
Object , 元素都向上转型了,但是这样虽然能够存储任意类型,但是使用起来就不方便了
比如我现在要存储学生成绩,不要存储其他类型,只要保存小数即可,如果我们还是要Object的话,那么取出数据之后一定要向下转型才能使用
,而引入泛型之后,我们可以指定存储的类型,那么编译器在编译阶段,就会检查添加的数据的类型是否匹配,不匹配就报错
泛型只能是引用数据局类型,不能是基本数据类型
优点 : 统一了数据类型,减少数据类型转换
缺点 : 只能存储单一类型的元素
就是在集合声明的时候指定了该集合的数据类型,指明了类型之后,再向集合中添加数据的时候,编译器就会对数据类型进行校验
虽然指定了泛型,但是 存进去的元素 还是会发生向上转型为Object类型
只是 取出来的时候,可以直接获取元素类型,不需要强制类型转换
泛型常用的标记 T , ? , E , K , V
T type : 表示是一个java类型
E Element : 元素,表示集合或者数组中的数据
KV : key,value 键值对
? : 表示一个不确定的类型
如果 人家规定了泛型,可以让我们指定数据类型,如果我们不指定的情况下,默认是Object
3.2 使用
不使用泛型
什么也能放
但是获取使用的时候,需要向下 转型 比较麻烦
package com.demo._Generic;
import java.util.HashSet;
import java.util.Set;
/**
* 类型检查 : 编译过程中,检查数据类型是否匹配
*
* 什么是泛型 : 集合就跟数组一样,都是只能放同一种数据类型的,那么为什么集合中什么都能放呢?
* Object , 元素都向上转型了,但是这样虽然能够存储任意类型,但是使用起来就不方便了
*
* 比如我现在要存储学生成绩,不要存储其他类型,只要保存小数即可,如果我们还是要Object的话,那么取出数据之后一定要向下转型才能使用
* ,而引入泛型之后,我们可以指定存储的类型,那么编译器在编译阶段,就会检查添加的数据的类型是否匹配,不匹配就报错
*
* 泛型只能是引用数据局类型,不能是基本数据类型
*
* 优点 : 统一了数据类型,减少数据类型转换
* 缺点 : 只能存储单一类型的元素
*
就是在集合声明的时候指定了该集合的数据类型,指明了类型之后,再向集合中添加数据的时候,编译器就会对数据类型进行校验
*
*/
public class Generic_01 {
public static void main(String[] args) {
// 不使用泛型
Set s = new HashSet();
A a = new A();
B b = new B();
C c = new C();
s.add(a);
s.add(b);
s.add(c);
// 使用的时候,就需要向下转型
for (Object object : s) {
if (object instanceof A) {
A a1 = (A) object;
a1.m1();
}else if (object instanceof B) {
B b1 = (B) object;
b1.m2();
}else if (object instanceof C) {
C c1 = (C) object;
c1.m3();
}
}
}
}
class A{
public void m1(){
System.out.println("---");
}
}
class B{
public void m2(){
System.out.println("11111");
}
}
class C{
public void m3(){
System.out.println("====");
}
}
使用泛型之后
package com.demo._Generic;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 虽然指定了泛型,但是 存进去的元素 还是会发生向上转型为Object类型
*
* 只是 取出来的时候,可以直接获取元素类型,不需要强制类型转换
*
* 泛型常用的标记 T , ? , E , K , V
* T type : 表示是一个java类型
* E Element : 元素,表示集合或者数组中的数据
* KV : key,value 键值对
* ? : 表示一个不确定的类型
*
* 如果 人家规定了泛型,可以让我们指定数据类型,如果我们不指定的情况下,默认是Object
*
* @author 天亮教育-帅气多汁你泽哥
* @Date 2021年1月23日
*/
public class Generic_02 {
public static void main(String[] args) {
Set<String> strs = new HashSet<String>();
// 不能保存Integer
// strs.add(1);
strs.add("aa");
strs.add("bb");
strs.add("cc");
// 使用泛型的方式 都相同
// 虽然指定了泛型,但是 存进去的元素 还是会发生向上转型为Object类型
// 只是 取出来的时候,可以直接获取元素类型,不需要强制类型转换
List<Integer> list = new ArrayList<Integer>();
for (String string : strs) {
System.out.println(string);
}
}
}
虽然指定了泛型,但是 存进去的元素 还是会发生向上转型为Object类型
只是 取出来的时候,可以直接获取元素类型,不需要强制类型转换
3.3 自定义泛型
package com.demo._Generic;
public class Generic_04 {
public static void main(String[] args) {
MyClass mc = new MyClass();
mc.m1(2);
// 默认是Object 想 传什么 就穿什么
mc.m1("asd");
MyClass<String> class1 = new MyClass<String>();
// 只能传递String
// class1.m1(213);
class1.m1("asdasd");
}
}
// T就相当于是个标签,占位符
// 就是这里需要客户端传递一个类型,用传递的类型替换这个T
// 如果你不传,默认是Object
class MyClass<T> {
public void m1(T t) {
System.out.println(t);
}
}
Map存储转换为List存储,并且要求使用value值进行排序
package com.demo._Map;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Map转换为list 并以value进行排序
*/
public class Map_05 {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("a", 1);
map.put("b", 2);
map.put("c", 1);
map.put("d", 4);
map.put("e", 16);
// 1 map存储键值对 , 而List只能存储一个元素 (Entry)
// 2 map转换为Entry存储(entrySet)
Set<Entry<String, Integer>> entrySet = map.entrySet();
// 3 把set转换为List,泛型Entry
List<Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(
entrySet);
// System.out.println(list);
// 4 排序 , Comparator
Collections.sort(list, new Comparator<Entry<String, Integer>>() {
@Override
public int compare(Entry<String, Integer> o1,
Entry<String, Integer> o2) {
return o1.getValue() - o2.getValue();
}
});
// 打印
for (Entry<String, Integer> entry : list) {
System.out.println(entry);
}
}
}
文章浏览阅读565次。本文主要介绍如何使用C#通过OPC方式连接PLC,并提供了相应的程序和学习资料,以便读者学习和使用。OPC服务器是一种软件,可以将PLC的数据转换为标准的OPC格式,允许其他软件通过标准接口读取或控制PLC的数据。此外,本文还提供了一些学习资料,包括OPC和PLC的基础知识,C#编程语言的教程和实例代码。这些资料可以帮助读者更好地理解和应用本文介绍的程序。1.该程序是通讯方式是CSharp通过OPC方式连接PLC,用这种方式连PLC不用考虑什么种类PLC,只要OPC服务器里有的PLC都可以连。_c#opc通信
文章浏览阅读1.6w次,点赞3次,收藏10次。实践环境物理机:Windows10教育版,操作系统版本 17763.914虚拟机:Ubuntu18.04.3桌面版在Hyper-V中的刚安装好Ubuntu虚拟机之后,会发现鼠标滑动很不顺畅,也不能向虚拟机中拖拽文件或者复制内容。在VMware中,可以通过安装VMware tools来使物理机和虚拟机之间达到更好的交互。在Hyper-V中,也有这样的工具。这款工具可以完成更好的鼠标交互,我的..._win10 hyper-v ubuntu18.04 文件拷贝
文章浏览阅读156次。前言互联网时代,瞬息万变。一个小小的走错,就有可能落后于别人。我们没办法去预测任何行业、任何职业未来十年会怎么样,因为未来谁都不能确定。只能说只要有互联网存在,程序员依然是个高薪热门行业。只要跟随着时代的脚步,学习新的知识。程序员是不可能会消失的,或者说不可能会没钱赚的。我们经常可以听到很多人说,程序员是一个吃青春饭的行当。因为大多数人认为这是一个需要高强度脑力劳动的工种,而30岁、40岁,甚至50岁的程序员身体机能逐渐弱化,家庭琐事缠身,已经不能再进行这样高强度的工作了。那么,这样的说法是对的么?_类初始化一个静态属性 为线程池
文章浏览阅读1w次,点赞13次,收藏43次。说来也是惭愧,一直以来,在装环境的时候都会从官网下载Maven。然后再在idea里配置Maven。以为从官网下载的Maven是必须的步骤,直到今天才得知,idea有捆绑的 Maven 我们只需要搞一个配置文件就行了无需再官网下载Maven包以后再在新电脑装环境的时候,只需要下载idea ,网上找一个Maven的配置文件 放到 默认的 包下面就可以了!也省得每次创建项目都要重新配一次Maven了。如果不想每次新建项目都要重新配置Maven,一种方法就是使用默认的配置,另一种方法就是配置 .._安装idea后是不是不需要安装maven了?
文章浏览阅读45次。家是我们一生中最重要的地方,小时候,我们在这里哭、在这里笑、在这里学习走路,在这里有我们最真实的时光,用相机把它记下吧。 很多家庭在拍摄孩子时有一个看法,认为儿童摄影团购必须是在风景秀丽的户外,即便是室内那也是像大酒店一样...
文章浏览阅读429次。Dockerfile介绍Dockerfile是构建镜像的指令文件,由一组指令组成,文件中每条指令对应linux中一条命令,在执行构建Docker镜像时,将读取Dockerfile中的指令,根据指令来操作生成指定Docker镜像。Dockerfile结构:主要由基础镜像信息、维护者信息、镜像操作指令、容器启动时执行指令。每行支持一条指令,每条指令可以携带多个参数。注释可以使用#开头。指令说明FROM 镜像 : 指定新的镜像所基于的镜像MAINTAINER 名字 : 说明新镜像的维护(制作)人,留下_rocker/r-base镜像
文章浏览阅读223次。该系统将提供便捷的信息发布、物业报修、社区互动等功能,为小区居民提供更加便利、高效的服务。引言: 随着城市化进程的加速,小区管理成为一个日益重要的任务。因此,设计一个基于微信小程序的小区管理系统成为了一项具有挑战性和重要性的毕设课题。本文将介绍该小区管理系统的设计思路和功能,以期为小区提供更便捷、高效的管理手段。四、总结与展望: 通过本次毕设项目,我们实现了一个基于微信小程序的小区管理系统,为小区居民提供了更加便捷、高效的服务。通过该系统的设计与实现,能够提高小区管理水平,提供更好的居住环境和服务。_ssm基于微信小程序的公寓生活管理系统
文章浏览阅读635次。文章来源i春秋入坑Ubuntu半年多了记得一开始学的时候基本一星期重装三四次=-= 尴尬了 觉得自己差不多可以的时候 就吧Windows10干掉了 c盘装Ubuntu 专心学习. 这里主要来说一下使用Ubuntu的正确姿势Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的开源GNU/Linux操作系统,Ubuntu 是基于DebianGNU/Linux,支..._ubuntu安装攻击工具包
文章浏览阅读335次。需求:C++中将BYTE型数组传递给Java中,考虑到内存释放问题,未采用通过返回值进行数据传递。public class demoClass{public native boolean getData(byte[] tempData);}JNIEXPORT jboolean JNICALL Java_com_core_getData(JNIEnv *env, jobject thisObj, jbyteArray tempData){ //resultsize为s..._jni引用byte[]
文章浏览阅读2.1k次,点赞5次,收藏30次。本教程代码开源:GitHub 欢迎star文章目录一、平面模型分割1. 代码2. 说明3. 运行二、圆柱模型分割1. 代码2. 说明3. 运行三、欧几里得聚类提取1. 代码2. 说明3. 运行四、区域生长分割1. 代码2. 说明3. 运行五、基于最小切割的分割1. 代码2. 说明3. 运行六、使用 ProgressiveMorphologicalFilter 分割地面1. 代码2. 说明3. 运行一、平面模型分割在本教程中,我们将学习如何对一组点进行简单的平面分割,即找到支持平面模型的点云中的所有._pclpy.pcl.pointcloud.pointxyzi转为numpy
文章浏览阅读141次。一 其实在 skyeye 上移植 arm-linux 并非难事,网上也有不少资料, 只是大都遗漏细节, 以致细微之处卡壳,所以本文力求详实清析, 希望能对大家有点用处。本文旨在将 arm-linux 在 skyeye 上搭建起来,并在 arm-linux 上能成功 mount NFS 为目标, 最终我们能在 arm-linux 里运行我们自己的应用程序. 二 安装 Sky..._nfs启动 arm
文章浏览阅读598次,点赞2次,收藏5次。00为了形成一个体系,想将前面学过的一些东西都拉来放在一起总结总结,方便学习,方便记忆。攻防世界 Pwn 新手攻防世界 Pwn 进阶 第一页01 4-ReeHY-main-100超详细的wp1超详细的wp203 format2栈迁移的两种作用之一:栈溢出太小,进行栈迁移从而能够写入更多shellcode,进行更多操作。栈迁移一篇搞定有个陌生的函数。C 库函数 void *memcpy(void *str1, const void *str2, size_t n) 从存储区 str2 _pwn snprintf