• 关于

    C#集合(Collection)

    的搜索结果

回答

Collection 总接口 --| List 特征 有序 可重复 ----| ArrayList 底层维护的是一个Object类型的数组,如果使用无参构造方法创建ArrayList集合,默认的容量为10 ​ 用带有参数的构造方法,创建ArrayList集合,传入的initCapacity是多少,容量就是多少 ​ 特征: 增删慢 查找快 ​ newCapacity = oldCapacity + (oldCapacity >> 1) 二进制位运算 ----| LinkedList 底层维护的是一个双向链表 特征是增删快 查找慢 ----| Vector 线程安全的ArrayList 和ArrayList基本相同,JDK1.0的古老产物。效率低于ArrayList --| Set 特征 无序 不可重复 ----| HashSet 底层维护是一个哈希表,存储效率极高 ​ 一个自定义类对象放入到HashSet中,需要经历如下过程: ​ 通过当前类对象的HashCode,获取到当前类对象的哈希值,进行移位运算,计算出当前元素应该保存到哈希表中的位置。 ​ 情况1: 当前位置没有元素,直接放入 ​ 情况2: 当前位置已经存在其他元素。需要调用该元素的equals方法,进行比较,如果比较结果为两个元素不同,能够放入,两个元素相同,不能放入。 ----| TreeSet 树形结构的Set集合 ​ 能够放入TreeSet中的元素必须有自然顺序,或者提供【比较规则】 ​ 一个自定义类对象,想要放入到TreeSet集合中,有两种方式 ​ 1. 当前类【遵从】Comparable接口,实现compareTo(Object o)方法 ​ 2. 实现一个自定义的比较器【遵从】Comparator接口,实现compare(Object o1, Object o2)方法 Collection中的方法 //添加方法: add(Object o) //添加指定元素 addAll(Collection c) //添加指定集合 //删除方法: remove(Object o) //删除指定元素 removeAll(Collection c) //输出两个集合的交集 retainAll(Collection c) //保留两个集合的交集 clear() //清空集合 //查询方法: size() //集合中的有效元素个数 toArray() //将集合中的元素转换成Object类型数组 //判断方法: isEmpty() //判断是否为空 equals(Object o) //判断是否与指定元素相同 contains(Object o) //判断是否包含指定元素 containsAll(Collection c) //判断是否包含指定集合 List中的方法 //添加方法: add(int index, Object o) //向指定位置添加元素 addAll(int index, Collection c) //向指定位置添加集合 //删除方法 remove(int index) //删除指定元素 //查询方法: get(int index) //获取指定位置的元素 indexOf(Object o) //获取指定元素的位置 lastIndexOf(Object o) //获取指定元素最后一次出现的位置 //修改方法: subList(int fromIndex, int toIndex) //截取子集合从fromIndex到toIndex,要头不要尾 set(int index, Object o) //修改指定位置的元素 ArrayList中特有的方法 ensureCapacity(int minCapactiy) //判断当前数组中的元素个数是否大于指定的minCapacity trimToSize() //修改数组容量为当前数组有效元素个数 LinkedList中特有的方法 //查询方法: getFirst() //获取集合中的第一个元素 getLast() //获取集合中的最后一个元素 //添加方法: addFirst(Object o) //在集合的第一个位置添加指定元素 addLast(Object o) //在集合的最后一个位置添加指定元素 //删除方法: removeFirst() //删除集合中的第一个元素 removeLast() //删除集合中的最后一个元素 Collection中的迭代器Iterator方法 Iterator iterator(); //迭代器构造方法 boolean hasNext() //判断是否有下一个元素 Object next() //获取当前元素 void remove() //删除通过next()获取的元素,在next()之后使用,不可以单独使用 List中的迭代器 ListIterator方法 ListIterator listIterator(); //迭代器构造函数 boolean hasNext() //判断是否有下一个元素 boolean hasPrevious() //判断是否有上一个元素 Object next() //获取当前元素 Object previous() //获取上一个元素 void remove() //删除通过next()获取的元素,在next()之后使用,不可以单独使用 add(Object o) //添加指定元素 set(Object o) //修改指定元素 int nextIndex() //获取当前元素所在位置

景凌凯 2020-04-07 17:20:03 0 浏览量 回答数 0

问题

迭代元素的时候用集合的remove()方法不会报错 ?报错

爱吃鱼的程序员 2020-06-23 21:02:29 0 浏览量 回答数 1

回答

"Collection接口里定义了如下操作集合元素的方法。 boolean add(Object o):该方法用于向集合里添加一个元素。如果集合对象被添加操作改变了,则返回true。 boolean addAll(Collection c):该方法把集合c里的所有元素添加到指定集合里。如果集合对象被添加操作改变了,则返回true。 void clear():清除集合里的所有元素,将集合长度变为0。 boolean contains(Object o):返回集合里是否包含指定元素。 boolean containsAll(Collection c):返回集合里是否包含集合c里的所有元素。 boolean isEmpty():返回集合是否为空。当集合长度为0时返回true,否则返回false。 Iterator iterator():返回一个Iterator对象,用于遍历集合里的元素。 boolean remove(Object o):删除集合中的指定元素o,当集合中包含了一个或多个元素o时,这些元素将被删除,该方法将返回true。 boolean removeAll(Collection c):从集合中删除集合c里包含的所有元素(相当于用调用该方法的集合减集合c),如果删除了一个或一个以上的元素,则该方法返回true。 boolean retainAll(Collection c):从集合中删除集合c里不包含的元素(相当于把调用该方法的集合变成该集合和集合c的交集),如果该操作改变了调用该方法的集合,则该方法返回true。 int size():该方法返回集合里元素的个数。 Object[]toArray():该方法把集合转换成一个数组,所有的集合元素变成对应的数组元素。"

星尘linger 2020-04-07 13:34:48 0 浏览量 回答数 0

阿里云试用中心,为您提供0门槛上云实践机会!

0元试用32+款产品,最高免费12个月!拨打95187-1,咨询专业上云建议!

回答

以下实例演示了如何遍历从Collection接口延伸出的List、Set和以键值对形式作存储的Map类型的集合,以下我们分别使用了普通for,增强型的 for ,iterator 等方式来遍历集合: List与Set类型集合的遍历 Main.java 文件 import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; public class Main { public static void main(String[] args) { // List集合的遍历 listTest(); // Set集合的遍历 setTest(); } private static void setTest() { Set set = new HashSet (); set.add("JAVA"); set.add("C"); set.add("C++"); // 重复数据添加失败 set.add("JAVA"); set.add("JAVASCRIPT"); // 使用iterator遍历set集合 Iterator<String> it = set.iterator(); while (it.hasNext()) { String value = it.next(); System.out.println(value); } // 使用增强for循环遍历set集合 for(String s: set){ System.out.println(s); } } // 遍历list集合 private static void listTest() { List list = new ArrayList (); list.add("菜"); list.add("鸟"); list.add("教"); list.add("程"); list.add("www.runoob.com"); // 使用iterator遍历 Iterator<String> it = list.iterator(); while (it.hasNext()) { String value = it.next(); System.out.println(value); } // 使用传统for循环进行遍历 for (int i = 0, size = list.size(); i < size; i++) { String value = list.get(i); System.out.println(value); } // 使用增强for循环进行遍历 for (String value : list) { System.out.println(value); } } } 以上代码运行输出结果为: 菜 鸟 教 程 www.runoob.com 菜 鸟 教 程 www.runoob.com 菜 鸟 教 程 www.runoob.com JAVA JAVASCRIPT C++ C JAVA JAVASCRIPT C++ C 关于Map类型集合的遍历 以下实例我们使用了 HashMap 的 keySet()与entrySet()方法来遍历集合: /* author by runoob.com Main.java */ import java.util.Map; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.Map.Entry; //增强For循环 public class Main { public static void main(String[] args) { // 创建一个HashMap对象,并加入了一些键值对。 Map<String, String> maps = new HashMap<String, String>(); maps.put("1", "PHP"); maps.put("2", "Java"); maps.put("3", "C"); maps.put("4", "C++"); maps.put("5", "HTML"); // 传统的遍历map集合的方法1; keySet() //traditionalMethod1(maps); // 传统的遍历map集合的方法2; entrySet() //traditionalMethod2(maps); // 使用增强For循环来遍历map集合方法1; keySet() //strongForMethod1(maps); // 使用增强For循环来遍历map集合方法2; entrySet() strongForMethod2(maps); } private static void strongForMethod2(Map<String, String> maps) { Set<Entry<String, String>> set = maps.entrySet(); for (Entry<String, String> entry : set) { String key = entry.getKey(); String value = entry.getValue(); System.out.println(key + " : " + value); } } private static void strongForMethod1(Map<String, String> maps) { Set set = maps.keySet(); for (String s : set) { String key = s; String value = maps.get(s); System.out.println(key + " : " + value); } } // 使用entrySet()方法,获取maps集合中的每一个键值对, private static void traditionalMethod2(Map<String, String> maps) { Set<Map.Entry<String, String>> sets = maps.entrySet(); // 取得迭代器遍历出对应的值。 Iterator<Entry<String, String>> it = sets.iterator(); while (it.hasNext()) { Map.Entry<String, String> entry = (Entry<String, String>) it.next(); String key = entry.getKey(); String value = entry.getValue(); System.out.println(key + " : " + value); } } // 使用keySet()方法,获取maps集合中的所有键,遍历键取得所对应的值。 private static void traditionalMethod1(Map<String, String> maps) { Set sets = maps.keySet(); // 取得迭代器遍历出对应的值 Iterator it = sets.iterator(); while (it.hasNext()) { String key = it.next(); String value = maps.get(key); System.out.println(key + " : " + value); } } } 以上代码运行输出结果为: 1 : PHP 2 : Java 3 : C 4 : C++ 5 : HTML

问问小秘 2020-02-13 17:21:28 0 浏览量 回答数 0

回答

不可以。但是可以将map转成set后再使用foreach语句。 1)、作用:对存储对象的容器进行迭代: 数组 collection map 2)、增强for循环迭代数组: String [] arr = {"a", "b", "c"};//数组的静态定义方式,只试用于数组首次定义的时候 for(String s : arr) { System.out.println(s); } 3)、单列集合 Collection: List list = new ArrayList(); list.add("aaa"); // 增强for循环, 没有使用泛型的集合能不能使用增强for循环迭代?能 for(Object obj : list) { String s = (String) obj; System.out.println(s); } 4)、双列集合 Map: Map map = new HashMap(); map.put("a", "aaa"); // 传统方式:必须掌握这种方式 Set entrys = map.entrySet(); // 1.获得所有的键值对Entry对象 iter = entrys.iterator(); // 2.迭代出所有的entry while(iter.hasNext()) { Map.Entry entry = (Entry) iter.next(); String key = (String) entry.getKey(); // 分别获得key和value String value = (String) entry.getValue(); System.out.println(key + "=" + value); } // 增强for循环迭代:原则上map集合是无法使用增强for循环来迭代的,因为增强for循环只能针对实现了Iterable接口的集合进行迭代;Iterable是jdk5中新定义的接口,就一个方法iterator方法,只有实现了Iterable接口的类,才能保证一定有iterator方法,java有这样的限定是因为增强for循环内部还是用迭代器实现的,而实际上,我们可以通过某种方式来使用增强for循环。 for(Object obj : map.entrySet()) { Map.Entry entry = (Entry) obj; // obj 依次表示Entry System.out.println(entry.getKey() + "=" + entry.getValue()); }

YDYK 2020-04-26 16:38:47 0 浏览量 回答数 0

回答

以下实例演示了如何使用 Collection 和 Listiterator 类的 listIterator() 和 collection.reverse() 方法来反转集合中的元素: Main.java 文件 import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.ListIterator; class Main { public static void main(String[] args) { String[] coins = { "A", "B", "C", "D", "E" }; List l = new ArrayList(); for (int i = 0; i < coins.length; i++) l.add(coins[i]); ListIterator liter = l.listIterator(); System.out.println("反转前"); while (liter.hasNext()) System.out.println(liter.next()); Collections.reverse(l); liter = l.listIterator(); System.out.println("反转后"); while (liter.hasNext()) System.out.println(liter.next()); } } 以上代码运行输出结果为: 反转前 A B C D E 反转后 E D C B A

问问小秘 2020-02-13 17:22:53 0 浏览量 回答数 0

问题

jfreechart的TimeSeriesChart时间轴TimeSeries问题?报错

爱吃鱼的程序员 2020-06-15 19:26:26 0 浏览量 回答数 1

回答

有许多不同的方法来表示顶点,边和图。这是一个过于简化的: 定义方向边: class Edge { private Vertex to; private int weight; public Edge(Vertex to, int weight) { super(); this.to = to; this.weight = weight; } Vertex getTo() { return to; } int getWeight() { return weight; } //todo override hashCode() } 定义一个顶点,以便每个顶点都有一个Edges 的集合到它的: class Vertex { private String label; private Set<Edge> edges; //collection of edges to neighbors public Vertex(String pageObject) { this.label = pageObject; edges = new HashSet<>(); } String getLabel() { return label; } boolean addEdge(Edge edge){ return edges.add(edge); } List<Edge> getEdges() { return new ArrayList<>(edges); } //todo override hashCode() } 定义一个包含Vertex对象集合的Graph: class Graph{ private Set<Vertex> vertices; //collection of all verices public Graph() { vertices = new HashSet<>(); } List<Vertex> getVertices() { return new ArrayList<>(vertices); } boolean addVertex(Vertex vertex){ return vertices.add(vertex); } } 构建图表: public static void main(String[] args) { Graph graph = new Graph(); //construct vertices Vertex v1 = new Vertex("1"); Vertex v2 = new Vertex("2"); Vertex v3 = new Vertex("3"); Vertex v4 = new Vertex("4"); Vertex v5 = new Vertex("5"); v1.addEdge(new Edge(v2, 1)); //connect v1 v2 v2.addEdge(new Edge(v1, 1)); v2.addEdge(new Edge(v3, 2)); //connect v2 v3 v3.addEdge(new Edge(v2, 2)); v2.addEdge(new Edge(v4, 3)); //connect v2 v4 v4.addEdge(new Edge(v2, 3)); v4.addEdge(new Edge(v5, 1)); //connect v4 v5 v5.addEdge(new Edge(v4, 1)); graph.addVertex(v1); graph.addVertex(v2); graph.addVertex(v3); graph.addVertex(v4); graph.addVertex(v5); }

刘琨1227 2019-12-02 02:08:53 0 浏览量 回答数 0

回答

这是逆。虽然matplotlib可以做几乎所有的事情,但是seaborn只提供了一小部分选项。 因此,使用matplotlib,您可以绘制如下所示的圆形补丁集合。 注意:你也可以使用散点图,但是由于散点的大小是绝对单位,所以很难将它们缩放到网格中。 import numpy as np import matplotlib.pyplot as plt from matplotlib.collections import PatchCollection N = 10 M = 11 ylabels = ["".join(np.random.choice(list("PQRSTUVXYZ"), size=7)) for _ in range(N)] xlabels = ["".join(np.random.choice(list("ABCDE"), size=3)) for _ in range(M)] x, y = np.meshgrid(np.arange(M), np.arange(N)) s = np.random.randint(0, 180, size=(N,M)) c = np.random.rand(N, M)-0.5 fig, ax = plt.subplots() R = s/s.max()/2 circles = [plt.Circle((j,i), radius=r) for r, j, i in zip(R.flat, x.flat, y.flat)] col = PatchCollection(circles, array=c.flatten(), cmap="RdYlGn") ax.add_collection(col) ax.set(xticks=np.arange(M), yticks=np.arange(N), xticklabels=xlabels, yticklabels=ylabels) ax.set_xticks(np.arange(M+1)-0.5, minor=True) ax.set_yticks(np.arange(N+1)-0.5, minor=True) ax.grid(which='minor') fig.colorbar(col) plt.show()

kun坤 2019-12-28 13:53:31 0 浏览量 回答数 0

问题

写了一个简单的excel读取类,待扩展更新:报错

kun坤 2020-06-07 20:00:55 0 浏览量 回答数 1

回答

"Collections还提供了如下用于查找、替换集合元素的常用方法。 static int binarySearch(List list,Object key):使用二分搜索法搜索指定的List集合,以获得指定对象在List集合中的索引。如果要使该方法可以正常工作,则必须保证List中的元素已经处于有序状态。 static Object max(Collection coll):根据元素的自然顺序,返回给定集合中的最大元素。 static Object max(Collection coll,Comparator comp):根据Comparator指定的顺序,返回给定集合中的最大元素。 static Object min(Collection coll):根据元素的自然顺序,返回给定集合中的最小元素。 static Object min(Collection coll,Comparator comp):根据Comparator指定的顺序,返回给定集合中的最小元素。 static void fill(List list,Object obj):使用指定元素obj替换指定List集合中的所有元素。 static int frequency(Collection c,Object o):返回指定集合中指定元素的出现次数。 static int indexOfSubList(List source,List target):返回子List对象在父List对象中第一次出现的位置索引;如果父List中没有出现这样的子List,则返回-1。 static int lastIndexOfSubList(List source,List target):返回子List对象在父List对象中最后一次出现的位置索引;如果父List中没有出现这样的子List,则返回-1。 static boolean replaceAll(List list,Object oldVal,Object newVal):使用一个新值newVal替换List对象的所有旧值oldVal。"

星尘linger 2020-04-12 09:59:18 0 浏览量 回答数 0

回答

"List作为Collection接口的子接口,当然可以使用Collection接口里的全部方法。而且由于List是有序集合,因此List集合里增加了一些根据索引来操作集合元素的方法。 void add(int index,Object element):将元素element插入到List集合的index处。 boolean addAll(int index,Collection c):将集合c所包含的所有元素都插入到List集合的index处。 Object get(int index):返回集合index索引处的元素。 int indexOf(Object o):返回对象o在List集合中第一次出现的位置索引。 int lastIndexOf(Object o):返回对象o在List集合中最后一次出现的位置索引。 Object remove(int index):删除并返回index索引处的元素。 Object set(int index,Object element):将index索引处的元素替换成element对象,返回新元素。 List subList(int fromIndex,int toIndex):返回从索引fromIndex(包含)到索引toIndex(不包含)处所有集合元素组成的子集合。"

星尘linger 2020-04-12 00:07:10 0 浏览量 回答数 0

回答

请注意,这些尺寸检查并不是必需的。空列表将导致空流,因此将不会应用任何内容。唯一的好处是您可以避免完全创建流,但是我非常怀疑性能差异是否会很明显。 如果要将潜在的null集合转换为流,则可能需要使用一个小的辅助函数: public <T> Stream<T> collectionToStream(Collection<T> collection) { return Optional.ofNullable(collection).map(Collection::stream).orElseGet(Stream::empty); } 使用forEach()您可以执行以下操作: private void createNewOrder(IPadPOSOrderDTO iPadPOSOrderDTO) { IPadPOSOrderV2 order = mapper.map(iPadPOSOrderDTO, IPadPOSOrderV2.class); collectionToStream(order.getOrderV2Bills()).forEach( orderBill -> { orderBill.setOrder(order); collectionToStream(orderBill.getiPadPOSOrderV2BillItems()).forEach(orderBillItem -> { orderBillItem.setiPadPOSOrderV2Bill(orderBill); orderBillItem.setOrderId(order.getOrderId()); } } } } sessionFactory.getCurrentSession().save(order); } 请注意,这与您的初始代码没有什么不同,因此您应该考虑这种转换是否有意义。 将您的嵌套循环转换为完全顺序的流会比较困难,最后也没有太大的不同,因为您不能只将平面映射orderBill到orderBillItem。这样做将无法在orderBill下游使用,因此您必须orderBillItem.setiPadPOSOrderV2Bill(orderBill); 在返回嵌套流之前进行调用。最终将得到与上面非常相似的代码,并且没有任何好处,因为您没有使用返回的流。 回答来源:Stack Overflow

montos 2020-03-27 15:32:36 0 浏览量 回答数 0

问题

如何与Spring和百里香建立一对多关系?

养狐狸的猫 2019-12-01 19:59:27 11 浏览量 回答数 0

回答

该答案详细说明了如何在Swift 4.2+中使用快速统一的算法(Fisher-Yates)进行改组,以及如何在各个早期版本的Swift中添加相同的功能。每个Swift版本的命名和行为都与该版本的变异和非变异排序方法匹配。 迅捷4.2+ shuffle并且shuffled是原生的Swift 4.2。用法示例: let x = [1, 2, 3].shuffled() // x == [2, 3, 1] let fiveStrings = stride(from: 0, through: 100, by: 5).map(String.init).shuffled() // fiveStrings == ["20", "45", "70", "30", ...] var numbers = [1, 2, 3, 4] numbers.shuffle() // numbers == [3, 2, 1, 4] Swift 4.0和4.1 这些扩展将shuffle()方法添加到任何可变集合(数组和不安全的可变缓冲区),并shuffled()在任何序列上添加方法: extension MutableCollection { /// Shuffles the contents of this collection. mutating func shuffle() { let c = count guard c > 1 else { return } for (firstUnshuffled, unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) { // Change `Int` in the next line to `IndexDistance` in < Swift 4.1 let d: Int = numericCast(arc4random_uniform(numericCast(unshuffledCount))) let i = index(firstUnshuffled, offsetBy: d) swapAt(firstUnshuffled, i) } } } extension Sequence { /// Returns an array with the contents of this sequence, shuffled. func shuffled() -> [Element] { var result = Array(self) result.shuffle() return result } } 与上述Swift 4.2示例中的用法相同。 迅捷3 这些扩展将shuffle()方法添加到任何可变集合中,并将shuffled()方法添加到任何序列中: extension MutableCollection where Indices.Iterator.Element == Index { /// Shuffles the contents of this collection. mutating func shuffle() { let c = count guard c > 1 else { return } for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) { // Change `Int` in the next line to `IndexDistance` in < Swift 3.2 let d: Int = numericCast(arc4random_uniform(numericCast(unshuffledCount))) guard d != 0 else { continue } let i = index(firstUnshuffled, offsetBy: d) self.swapAt(firstUnshuffled, i) } } } extension Sequence { /// Returns an array with the contents of this sequence, shuffled. func shuffled() -> [Iterator.Element] { var result = Array(self) result.shuffle() return result } } 与上述Swift 4.2示例中的用法相同。 迅捷2 (过时的语言:自2018年7月起,您将无法使用Swift 2.x在iTunes Connect上发布) extension MutableCollectionType where Index == Int { /// Shuffle the elements of self in-place. mutating func shuffleInPlace() { // empty and single-element collections don't shuffle if count < 2 { return } for i in startIndex ..< endIndex - 1 { let j = Int(arc4random_uniform(UInt32(count - i))) + i guard i != j else { continue } swap(&self[i], &self[j]) } } } extension CollectionType { /// Return a copy of self with its elements shuffled. func shuffle() -> [Generator.Element] { var list = Array(self) list.shuffleInPlace() return list } } 用法: [1, 2, 3].shuffle() // [2, 3, 1] let fiveStrings = 0.stride(through: 100, by: 5).map(String.init).shuffle() // ["20", "45", "70", "30", ...] var numbers = [1, 2, 3, 4] numbers.shuffleInPlace() // [3, 2, 1, 4] 斯威夫特1.2 (过时的语言:自2018年7月起,您将无法使用Swift 1.x在iTunes Connect上发布) shuffle 作为变异数组方法 此扩展使您可以Array在适当的位置随机排列一个可变实例: extension Array { mutating func shuffle() { if count < 2 { return } for i in 0..<(count - 1) { let j = Int(arc4random_uniform(UInt32(count - i))) + i swap(&self[i], &self[j]) } } } var numbers = [1, 2, 3, 4, 5, 6, 7, 8] numbers.shuffle() // e.g., numbers == [6, 1, 8, 3, 2, 4, 7, 5] shuffled 作为非变异数组方法 通过此扩展,您可以检索Array实例的随机组合副本: extension Array { func shuffled() -> [T] { if count < 2 { return self } var list = self for i in 0..<(list.count - 1) { let j = Int(arc4random_uniform(UInt32(list.count - i))) + i swap(&list[i], &list[j]) } return list } } let numbers = [1, 2, 3, 4, 5, 6, 7, 8] let mixedup = numbers.shuffled() // e.g., mixedup == [6, 1, 8, 3, 2, 4, 7, 5] 问题来源于stack overflow

保持可爱mmm 2020-01-16 15:08:15 0 浏览量 回答数 0

回答

"Map接口中定义了如下常用的方法。 void clear():删除该Map对象中的所有key-value对。 boolean containsKey(Object key):查询Map中是否包含指定的key,如果包含则返回true。 boolean containsValue(Object value):查询Map中是否包含一个或多个value,如果包含则返回true。 Set entrySet():返回Map中包含的key-value对所组成的Set集合,每个集合元素都是Map.Entry(Entry是Map的内部类)对象。 Object get(Object key):返回指定key所对应的value;如果此Map中不包含该key,则返回null。 boolean isEmpty():查询该Map是否为空(即不包含任何key-value对),如果为空则返回true。 Set keySet():返回该Map中所有key组成的Set集合。 Object put(Object key,Object value):添加一个key-value对,如果当前Map中已有一个与该key相等的key-value对,则新的key-value对会覆盖原来的key-value对。 void putAll(Map m):将指定Map中的key-value对复制到本Map中。 Object remove(Object key):删除指定key所对应的key-value对,返回被删除key所关联的value,如果该key不存在,则返回null。 int size():返回该Map里的key-value对的个数。 Collection values():返回该Map里所有value组成的Collection。"

星尘linger 2020-04-12 09:26:19 0 浏览量 回答数 0

回答

以 oschina 为例: 生成项目 $ scrapy startproject oschina $ cd oschina 配置 编辑 settings.py, 加入以下(主要是User-agent和piplines): USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0' LOG_LEVEL = 'ERROR' RETRY_ENABLED = False DOWNLOAD_TIMEOUT = 10 ITEM_PIPELINES = { 'oschina.pipelines.SomePipeline': 300, } 编辑 items.py, 内容如下: # -- coding: utf-8 -- import scrapy class OschinaItem(scrapy.Item): Link = scrapy.Field() LinkText = scrapy.Field() 编辑 pipelines.py, 内容如下: # -- coding: utf-8 -- import json from scrapy.exceptions import DropItem class OschinaPipeline(object): def init(self): self.file = open('result.jl', 'w') self.seen = set() # 重复检测集合 def process_item(self, item, spider): if item['link'] in self.seen: raise DropItem('Duplicate link %s' % item['link'])self.seen.add(item['link']) line = json.dumps(dict(item), ensure_ascii=False) + '\n' self.file.write(line) return item 生成模板spider然后修改: $ scrapy genspider scrapy_oschina oschina.net # scrapy genspider 爬虫名 要爬取的域名编辑 spiders/scrapy_oschina.py: # -- coding: utf-8 -- import scrapy from oschina.items import OschinaItem class ScrapyOschinaSpider(scrapy.Spider): name = "scrapy_oschina" allowed_domains = ["oschina.net"] start_urls = ( ' http://www.oschina.net/', ) def parse(self, response): sel = scrapy.Selector(response) links_in_a_page = sel.xpath('//a[@href]') # 页面内的所有链接for link_sel in links_in_a_page: item = OschinaItem() link = str(link_sel.re('href="(.*?)"')[0]) # 每一个urlif link: if not link.startswith('http'): # 处理相对URLlink = response.url + link yield scrapy.Request(link, callback=self.parse) # 生成新的请求, 递归回调self.parseitem['link'] = link link_text = link_sel.xpath('text()').extract() # 每个url的链接文本, 若不存在设为Noneif link_text: item['link_text'] = str(link_text[0].encode('utf-8').strip())else: item['link_text'] = None #print item['link'], # 取消注释在屏幕显示结果#print item['link_text'] yield item 运行: scrapy crawl scrapy_oschina 结果保存在 oschina.jl 文件中, 目的只是为了介绍怎样编写item pipeline,如果要将所有爬取的item都保存到同一个JSON文件, 需要使用 Feed exports截图如下: 运行截图 文件内容 保存数据到mongoDB 在 pipelines.py中加入: import pymongo class MongoPipeline(object): def init(self, mongo_host, mongo_port, mongo_db): self.mongo_host = mongo_host self.mongo_port = mongo_port self.mongo_db = mongo_db @classmethod def from_crawler(cls, crawler): return cls( mongo_host=crawler.settings.get('MONGO_HOST'),mongo_port=crawler.settings.get('MONGO_PORT'),mongo_db=crawler.settings.get('MONGO_DB', 'doubandb'),) def open_spider(self, spider): self.client = pymongo.MongoClient(self.mongo_host, self.mongo_port)self.db = self.client[self.mongo_db] def close_spider(self, spider): self.client.close() def process_item(self, item, spider): collection_name = item.class.__name__self.db[collection_name].insert(dict(item))return item 在settings.py设置相应的 MONGO_HOST(默认127.0.0.1),MONGO_PORT(默认27017), MONGO_DB, MONGO_COLLECTION, ITEM_PIPELINES字典加入这个项'scrapy_douban.pipelines.MongoPipeline':400,数字代表优先级, 越大越低 使用 XmlItemExporter 在pipelines.py添加: from scrapy.exporters import XmlItemExporterfrom scrapy import signals class XmlExportPipeline(object): def init(self): self.files = {} @classmethod def from_crawler(cls, crawler): pipeline = cls() crawler.signals.connect(pipeline.spider_opened, signals.spider_opened)crawler.signals.connect(pipeline.spider_closed, signals.spider_closed)return pipeline def spider_opened(self, spider): file = open('%s_urls.xml' % spider.name, 'w+b')self.files[spider] = file self.exporter = XmlItemExporter(file) self.exporter.start_exporting() def spider_closed(self, spider): self.exporter.finish_exporting() file = self.files.pop(spider) file.close() def process_item(self, item, spider): self.exporter.export_item(item) return item settings.py中 ITEM_PIPELINES 添加项 'oschina.pipelines.XmlExportPipeline':500, 答案来源于网络

养狐狸的猫 2019-12-02 03:01:49 0 浏览量 回答数 0

问题

如何在Python中键入提示通用数字类型?

is大龙 2020-03-24 12:29:50 0 浏览量 回答数 1

回答

最简单:将整个集合转储到Set中(使用Set(Collection)构造函数或Set.addAll),然后查看Set是否具有与ArrayList相同的大小。 List list = ...; Set set = new HashSet (list); if(set.size() < list.size()){ /* There are duplicates */ } 更新:如果我正确地理解了您的问题,那么您将获得二维的Block数组,如下所示: 块表[] []; 并且您想检测其中是否有重复的行? 在那种情况下,假设Block正确实现了“ equals”和“ hashCode”,我可以执行以下操作: for (Block[] row : table) { Set set = new HashSet (); for (Block cell : row) { set.add(cell); } if (set.size() < 6) { //has duplicate } } 我不确定语法是否100%,因此将其编写为可能更安全 for (int i = 0; i < 6; i++) { Set set = new HashSet (); for (int j = 0; j < 6; j++) set.add(table[i][j]); ... Set.add如果要添加的项已在集合中,则返回boolean false,因此,false如果您只想知道是否存在重复项,则您甚至可以短路并打包返回的任何添加项。

保持可爱mmm 2020-02-08 11:26:19 0 浏览量 回答数 0

回答

一、接口的默认方法 Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法,示例如下: interface Formula { double calculate(int a); default double sqrt(int a) { return Math.sqrt(a); } } Formula接口在拥有calculate方法之外同时还定义了sqrt方法,实现了Formula接口的子类只需要实现一个calculate方法,默认方法sqrt将在子类上可以直接使用。 Formula formula = new Formula() { @Override public double calculate(int a) { return sqrt(a * 100); } }; formula.calculate(100); // 100.0 formula.sqrt(16); // 4.0 文中的formula被实现为一个匿名类的实例,该代码非常容易理解,6行代码实现了计算 sqrt(a * 100)。在下一节中,我们将会看到实现单方法接口的更简单的做法。 译者注: 在Java中只有单继承,如果要让一个类赋予新的特性,通常是使用接口来实现,在C++中支持多继承,允许一个子类同时具有多个父类的接口与功能,在其他语言中,让一个类同时具有其他的可复用代码的方法叫做mixin。新的Java 8 的这个特新在编译器实现的角度上来说更加接近Scala的trait。 在C#中也有名为扩展方法的概念,允许给已存在的类型扩展方法,和Java 8的这个在语义上有差别。 二、Lambda 表达式 首先看看在老版本的Java中是如何排列字符串的: List<String> names = Arrays.asList("peter", "anna", "mike", "xenia"); Collections.sort(names, new Comparator<String>() { @Override public int compare(String a, String b) { return b.compareTo(a); } }); 只需要给静态方法 Collections.sort 传入一个List对象以及一个比较器来按指定顺序排列。通常做法都是创建一个匿名的比较器对象然后将其传递给sort方法。 在Java 8 中你就没必要使用这种传统的匿名对象的方式了,Java 8提供了更简洁的语法,lambda表达式: Collections.sort(names, (String a, String b) -> { return b.compareTo(a); }); 看到了吧,代码变得更段且更具有可读性,但是实际上还可以写得更短: Collections.sort(names, (String a, String b) -> b.compareTo(a)); 对于函数体只有一行代码的,你可以去掉大括号{}以及return关键字,但是你还可以写得更短点: Collections.sort(names, (a, b) -> b.compareTo(a)); Java编译器可以自动推导出参数类型,所以你可以不用再写一次类型。接下来我们看看lambda表达式还能作出什么更方便的东西来 三、函数式接口 Lambda表达式是如何在java的类型系统中表示的呢?每一个lambda表达式都对应一个类型,通常是接口类型。而“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。因为 默认方法 不算抽象方法,所以你也可以给你的函数式接口添加默认方法。 我们可以将lambda表达式当作任意只包含一个抽象方法的接口类型,确保你的接口一定达到这个要求,你只需要给你的接口添加 @FunctionalInterface 注解,编译器如果发现你标注了这个注解的接口有多于一个抽象方法的时候会报错的。 @FunctionalInterface interface Converter<F, T> { T convert(F from); } Converter<String, Integer> converter = (from) -> Integer.valueOf(from); Integer converted = converter.convert("123"); System.out.println(converted); // 123 需要注意如果@FunctionalInterface如果没有指定,上面的代码也是对的。 译者注 将lambda表达式映射到一个单方法的接口上,这种做法在Java 8之前就有别的语言实现,比如Rhino JavaScript解释器,如果一个函数参数接收一个单方法的接口而你传递的是一个function,Rhino 解释器会自动做一个单接口的实例到function的适配器,典型的应用场景有 org.w3c.dom.events.EventTarget 的addEventListener 第二个参数 EventListener。 四、方法与构造函数引用 前一节中的代码还可以通过静态方法引用来表示: Converter<String, Integer> converter = Integer::valueOf; Integer converted = converter.convert("123"); System.out.println(converted); // 123 Java 8 允许你使用 :: 关键字来传递方法或者构造函数引用,上面的代码展示了如何引用一个静态方法,我们也可以引用一个对象的方法: converter = something::startsWith; String converted = converter.convert("Java"); System.out.println(converted); // "J" 接下来看看构造函数是如何使用::关键字来引用的,首先我们定义一个包含多个构造函数的简单类: class Person { String firstName; String lastName; Person() {} Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } } 接下来我们指定一个用来创建Person对象的对象工厂接口: interface PersonFactory<P extends Person> { P create(String firstName, String lastName); } 这里我们使用构造函数引用来将他们关联起来,而不是实现一个完整的工厂: PersonFactory<Person> personFactory = Person::new; Person person = personFactory.create("Peter", "Parker"); 我们只需要使用 Person::new 来获取Person类构造函数的引用,Java编译器会自动根据PersonFactory.create方法的签名来选择合适的构造函数。 五、Lambda 作用域 在lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似。你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量。 六、访问局部变量 我们可以直接在lambda表达式中访问外层的局部变量: final int num = 1; Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + num); stringConverter.convert(2); // 3 但是和匿名对象不同的是,这里的变量num可以不用声明为final,该代码同样正确: int num = 1; Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + num); stringConverter.convert(2); // 3 不过这里的num必须不可被后面的代码修改(即隐性的具有final的语义),例如下面的就无法编译: int num = 1; Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + num); num = 3; 在lambda表达式中试图修改num同样是不允许的。 七、访问对象字段与静态变量 和本地变量不同的是,lambda内部对于实例的字段以及静态变量是即可读又可写。该行为和匿名对象是一致的: class Lambda4 { static int outerStaticNum; int outerNum; void testScopes() { Converter<Integer, String> stringConverter1 = (from) -> { outerNum = 23; return String.valueOf(from); }; Converter<Integer, String> stringConverter2 = (from) -> { outerStaticNum = 72; return String.valueOf(from); }; } } 八、访问接口的默认方法 还记得第一节中的formula例子么,接口Formula定义了一个默认方法sqrt可以直接被formula的实例包括匿名对象访问到,但是在lambda表达式中这个是不行的。 Lambda表达式中是无法访问到默认方法的,以下代码将无法编译: Formula formula = (a) -> sqrt( a * 100); Built-in Functional Interfaces JDK 1.8 API包含了很多内建的函数式接口,在老Java中常用到的比如Comparator或者Runnable接口,这些接口都增加了@FunctionalInterface注解以便能用在lambda上。 Java 8 API同样还提供了很多全新的函数式接口来让工作更加方便,有一些接口是来自Google Guava库里的,即便你对这些很熟悉了,还是有必要看看这些是如何扩展到lambda上使用的。 Predicate接口 Predicate 接口只有一个参数,返回boolean类型。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非): Predicate<String> predicate = (s) -> s.length() > 0; predicate.test("foo"); // true predicate.negate().test("foo"); // false Predicate<Boolean> nonNull = Objects::nonNull; Predicate<Boolean> isNull = Objects::isNull; Predicate<String> isEmpty = String::isEmpty; Predicate<String> isNotEmpty = isEmpty.negate(); Function 接口 Function 接口有一个参数并且返回一个结果,并附带了一些可以和其他函数组合的默认方法(compose, andThen): Function<String, Integer> toInteger = Integer::valueOf; Function<String, String> backToString = toInteger.andThen(String::valueOf); backToString.apply("123"); // "123" Supplier 接口 Supplier 接口返回一个任意范型的值,和Function接口不同的是该接口没有任何参数 Supplier personSupplier = Person::new; personSupplier.get(); // new Person Consumer 接口 Consumer 接口表示执行在单个参数上的操作。 Consumer greeter = (p) -> System.out.println("Hello, " + p.firstName); greeter.accept(new Person("Luke", "Skywalker")); Comparator 接口 Comparator 是老Java中的经典接口, Java 8在此之上添加了多种默认方法: Comparator comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName); Person p1 = new Person("John", "Doe"); Person p2 = new Person("Alice", "Wonderland"); comparator.compare(p1, p2); // > 0 comparator.reversed().compare(p1, p2); // < 0 Optional 接口 Optional 不是函数是接口,这是个用来防止NullPointerException异常的辅助类型,这是下一届中将要用到的重要概念,现在先简单的看看这个接口能干什么: Optional 被定义为一个简单的容器,其值可能是null或者不是null。在Java 8之前一般某个函数应该返回非空对象但是偶尔却可能返回了null,而在Java 8中,不推荐你返回null而是返回Optional。 Optional optional = Optional.of("bam"); optional.isPresent(); // true optional.get(); // "bam" optional.orElse("fallback"); // "bam" optional.ifPresent((s) -> System.out.println(s.charAt(0))); // "b" Stream 接口 java.util.Stream 表示能应用在一组元素上一次执行的操作序列。Stream 操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,这样你就可以将多个操作依次串起来。Stream 的创建需要指定一个数据源,比如 java.util.Collection的子类,List或者Set, Map不支持。Stream的操作可以串行执行或者并行执行。 首先看看Stream是怎么用,首先创建实例代码的用到的数据List: List stringCollection = new ArrayList<>(); stringCollection.add("ddd2"); stringCollection.add("aaa2"); stringCollection.add("bbb1"); stringCollection.add("aaa1"); stringCollection.add("bbb3"); stringCollection.add("ccc"); stringCollection.add("bbb2"); stringCollection.add("ddd1"); Java 8扩展了集合类,可以通过 Collection.stream() 或者 Collection.parallelStream() 来创建一个Stream。下面几节将详细解释常用的Stream操作: Filter 过滤 过滤通过一个predicate接口来过滤并只保留符合条件的元素,该操作属于中间操作,所以我们可以在过滤后的结果来应用其他Stream操作(比如forEach)。forEach需要一个函数来对过滤后的元素依次执行。forEach是一个最终操作,所以我们不能在forEach之后来执行其他Stream操作。 stringCollection .stream() .filter((s) -> s.startsWith("a")) .forEach(System.out::println); // "aaa2", "aaa1" Sort 排序 排序是一个中间操作,返回的是排序好后的Stream。如果你不指定一个自定义的Comparator则会使用默认排序。 stringCollection .stream() .sorted() .filter((s) -> s.startsWith("a")) .forEach(System.out::println); // "aaa1", "aaa2" 需要注意的是,排序只创建了一个排列好后的Stream,而不会影响原有的数据源,排序之后原数据stringCollection是不会被修改的。 System.out.println(stringCollection); // ddd2, aaa2, bbb1, aaa1, bbb3, ccc, bbb2, ddd1 Map 映射 中间操作map会将元素根据指定的Function接口来依次将元素转成另外的对象,下面的示例展示了将字符串转换为大写字符串。你也可以通过map来讲对象转换成其他类型,map返回的Stream类型是根据你map传递进去的函数的返回值决定的。 stringCollection .stream() .map(String::toUpperCase) .sorted((a, b) -> b.compareTo(a)) .forEach(System.out::println); // "DDD2", "DDD1", "CCC", "BBB3", "BBB2", "AAA2", "AAA1" Match 匹配 Stream提供了多种匹配操作,允许检测指定的Predicate是否匹配整个Stream。所有的匹配操作都是最终操作,并返回一个boolean类型的值。 boolean anyStartsWithA = stringCollection .stream() .anyMatch((s) -> s.startsWith("a")); System.out.println(anyStartsWithA); // true boolean allStartsWithA = stringCollection .stream() .allMatch((s) -> s.startsWith("a")); System.out.println(allStartsWithA); // false boolean noneStartsWithZ = stringCollection .stream() .noneMatch((s) -> s.startsWith("z")); System.out.println(noneStartsWithZ); // true Count 计数 计数是一个最终操作,返回Stream中元素的个数,返回值类型是long。 long startsWithB = stringCollection .stream() .filter((s) -> s.startsWith("b")) .count(); System.out.println(startsWithB); // 3 Reduce 规约 这是一个最终操作,允许通过指定的函数来讲stream中的多个元素规约为一个元素,规越后的结果是通过Optional接口表示的: Optional reduced = stringCollection .stream() .sorted() .reduce((s1, s2) -> s1 + "#" + s2); reduced.ifPresent(System.out::println); // "aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2" 并行Streams 前面提到过Stream有串行和并行两种,串行Stream上的操作是在一个线程中依次完成,而并行Stream则是在多个线程上同时执行。 下面的例子展示了是如何通过并行Stream来提升性能: 首先我们创建一个没有重复元素的大表 int max = 1000000; List values = new ArrayList<>(max); for (int i = 0; i < max; i++) { UUID uuid = UUID.randomUUID(); values.add(uuid.toString()); } 然后我们计算一下排序这个Stream要耗时多久, 串行排序: long t0 = System.nanoTime(); long count = values.stream().sorted().count(); System.out.println(count); long t1 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0); System.out.println(String.format("sequential sort took: %d ms", millis)); // 串行耗时: 899 ms 并行排序: long t0 = System.nanoTime(); long count = values.parallelStream().sorted().count(); System.out.println(count); long t1 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0); System.out.println(String.format("parallel sort took: %d ms", millis)); // 并行排序耗时: 472 ms 上面两个代码几乎是一样的,但是并行版的快了50%之多,唯一需要做的改动就是将stream()改为parallelStream()。 Map 前面提到过,Map类型不支持stream,不过Map提供了一些新的有用的方法来处理一些日常任务。 Map<Integer, String> map = new HashMap<>(); for (int i = 0; i < 10; i++) { map.putIfAbsent(i, "val" + i); } map.forEach((id, val) -> System.out.println(val)); 以上代码很容易理解, putIfAbsent 不需要我们做额外的存在性检查,而forEach则接收一个Consumer接口来对map里的每一个键值对进行操作。 下面的例子展示了map上的其他有用的函数: map.computeIfPresent(3, (num, val) -> val + num); map.get(3); // val33 map.computeIfPresent(9, (num, val) -> null); map.containsKey(9); // false map.computeIfAbsent(23, num -> "val" + num); map.containsKey(23); // true map.computeIfAbsent(3, num -> "bam"); map.get(3); // val33 接下来展示如何在Map里删除一个键值全都匹配的项 map.remove(3, "val3"); map.get(3); // val33 map.remove(3, "val33"); map.get(3); // null 另外一个有用的方法 map.getOrDefault(42, "not found"); // not found 对Map的元素做合并也变得很容易了: map.merge(9, "val9", (value, newValue) -> value.concat(newValue)); map.get(9); // val9 map.merge(9, "concat", (value, newValue) -> value.concat(newValue)); map.get(9); // val9concat Merge做的事情是如果键名不存在则插入,否则则对原键对应的值做合并操作并重新插入到map中。 九、Date API Java 8 在包java.time下包含了一组全新的时间日期API。新的日期API和开源的Joda-Time库差不多,但又不完全一样,下面的例子展示了这组新API里最重要的一些部分: Clock 时钟 Clock类提供了访问当前日期和时间的方法,Clock是时区敏感的,可以用来取代 System.currentTimeMillis() 来获取当前的微秒数。某一个特定的时间点也可以使用Instant类来表示,Instant类也可以用来创建老的java.util.Date对象。 Clock clock = Clock.systemDefaultZone(); long millis = clock.millis(); Instant instant = clock.instant(); Date legacyDate = Date.from(instant); // legacy java.util.Date Timezones 时区 在新API中时区使用ZoneId来表示。时区可以很方便的使用静态方法of来获取到。 时区定义了到UTS时间的时间差,在Instant时间点对象到本地日期对象之间转换的时候是极其重要的。 System.out.println(ZoneId.getAvailableZoneIds()); // prints all available timezone ids ZoneId zone1 = ZoneId.of("Europe/Berlin"); ZoneId zone2 = ZoneId.of("Brazil/East"); System.out.println(zone1.getRules()); System.out.println(zone2.getRules()); // ZoneRules[currentStandardOffset=+01:00] // ZoneRules[currentStandardOffset=-03:00] LocalTime 本地时间 LocalTime 定义了一个没有时区信息的时间,例如 晚上10点,或者 17:30:15。下面的例子使用前面代码创建的时区创建了两个本地时间。之后比较时间并以小时和分钟为单位计算两个时间的时间差: LocalTime now1 = LocalTime.now(zone1); LocalTime now2 = LocalTime.now(zone2); System.out.println(now1.isBefore(now2)); // false long hoursBetween = ChronoUnit.HOURS.between(now1, now2); long minutesBetween = ChronoUnit.MINUTES.between(now1, now2); System.out.println(hoursBetween); // -3 System.out.println(minutesBetween); // -239 LocalTime 提供了多种工厂方法来简化对象的创建,包括解析时间字符串。 LocalTime late = LocalTime.of(23, 59, 59); System.out.println(late); // 23:59:59 DateTimeFormatter germanFormatter = DateTimeFormatter .ofLocalizedTime(FormatStyle.SHORT) .withLocale(Locale.GERMAN); LocalTime leetTime = LocalTime.parse("13:37", germanFormatter); System.out.println(leetTime); // 13:37 LocalDate 本地日期 LocalDate 表示了一个确切的日期,比如 2014-03-11。该对象值是不可变的,用起来和LocalTime基本一致。下面的例子展示了如何给Date对象加减天/月/年。另外要注意的是这些对象是不可变的,操作返回的总是一个新实例。 LocalDate today = LocalDate.now(); LocalDate tomorrow = today.plus(1, ChronoUnit.DAYS); LocalDate yesterday = tomorrow.minusDays(2); LocalDate independenceDay = LocalDate.of(2014, Month.JULY, 4); DayOfWeek dayOfWeek = independenceDay.getDayOfWeek(); System.out.println(dayOfWeek); // FRIDAY 从字符串解析一个LocalDate类型和解析LocalTime一样简单: DateTimeFormatter germanFormatter = DateTimeFormatter .ofLocalizedDate(FormatStyle.MEDIUM) .withLocale(Locale.GERMAN); LocalDate xmas = LocalDate.parse("24.12.2014", germanFormatter); System.out.println(xmas); // 2014-12-24 LocalDateTime 本地日期时间 LocalDateTime 同时表示了时间和日期,相当于前两节内容合并到一个对象上了。LocalDateTime和LocalTime还有LocalDate一样,都是不可变的。LocalDateTime提供了一些能访问具体字段的方法。 LocalDateTime sylvester = LocalDateTime.of(2014, Month.DECEMBER, 31, 23, 59, 59); DayOfWeek dayOfWeek = sylvester.getDayOfWeek(); System.out.println(dayOfWeek); // WEDNESDAY Month month = sylvester.getMonth(); System.out.println(month); // DECEMBER long minuteOfDay = sylvester.getLong(ChronoField.MINUTE_OF_DAY); System.out.println(minuteOfDay); // 1439 只要附加上时区信息,就可以将其转换为一个时间点Instant对象,Instant时间点对象可以很容易的转换为老式的java.util.Date。 Instant instant = sylvester .atZone(ZoneId.systemDefault()) .toInstant(); Date legacyDate = Date.from(instant); System.out.println(legacyDate); // Wed Dec 31 23:59:59 CET 2014 格式化LocalDateTime和格式化时间和日期一样的,除了使用预定义好的格式外,我们也可以自己定义格式: DateTimeFormatter formatter = DateTimeFormatter .ofPattern("MMM dd, yyyy - HH:mm"); LocalDateTime parsed = LocalDateTime.parse("Nov 03, 2014 - 07:13", formatter); String string = formatter.format(parsed); System.out.println(string); // Nov 03, 2014 - 07:13 和java.text.NumberFormat不一样的是新版的DateTimeFormatter是不可变的,所以它是线程安全的。 关于时间日期格式的详细信息:http://download.java.net/jdk8/docs/api/java/time/format/DateTimeFormatter.html 十、Annotation 注解 在Java 8中支持多重注解了,先看个例子来理解一下是什么意思。 首先定义一个包装类Hints注解用来放置一组具体的Hint注解: @interface Hints { Hint[] value(); } @Repeatable(Hints.class) @interface Hint { String value(); } Java 8允许我们把同一个类型的注解使用多次,只需要给该注解标注一下@Repeatable即可。 例 1: 使用包装类当容器来存多个注解(老方法) @Hints({@Hint("hint1"), @Hint("hint2")}) class Person {} 例 2:使用多重注解(新方法) @Hint("hint1") @Hint("hint2") class Person {} 第二个例子里java编译器会隐性的帮你定义好@Hints注解,了解这一点有助于你用反射来获取这些信息: Hint hint = Person.class.getAnnotation(Hint.class); System.out.println(hint); // null Hints hints1 = Person.class.getAnnotation(Hints.class); System.out.println(hints1.value().length); // 2 Hint[] hints2 = Person.class.getAnnotationsByType(Hint.class); System.out.println(hints2.length); // 2 即便我们没有在Person类上定义@Hints注解,我们还是可以通过 getAnnotation(Hints.class) 来获取 @Hints注解,更加方便的方法是使用 getAnnotationsByType 可以直接获取到所有的@Hint注解。 另外Java 8的注解还增加到两种新的target上了: @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) @interface MyAnnotation {}

日你dady哟 2019-12-02 03:08:13 0 浏览量 回答数 0

问题

shiro redis 集群 session无法登陆?报错

爱吃鱼的程序员 2020-06-09 10:34:48 0 浏览量 回答数 1

回答

"Java 集合 ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等都是线程不安全的,也就是说,当多个并发线程向这些集合中存、取元素时,就可能会破坏这些集合的数据完整性。 如果程序中有多个线程可能访问以上这些集合,那么我们可以使用 Collections 提供的静态方法把这些集合包装成线程安全的集合。Collections提供了如下几个静态方法。 Collection synchronizedCollection(Collection c):返回指定 collection对应的线程安全的collection。 static List synchronizedList(List list):返回指定List对象对应的线程安全的List对象。 static<K,V>Map<K,V>synchronizedMap(Map<K,V>m):返回指定Map对象对应的线程安全的Map对象。 static Set synchronizedSet(Set s):返回指定Set对象对应的线程安全的Set对象。 static <K,V>SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m):返回指定SortedMap对象对应的线程安全的SortedMap对象。 static SortedSet synchronizedSortedSet(SortedSet s):返回指定SortedSet对象对应的线程安全的SortedSet对象。"

星尘linger 2020-04-12 19:17:42 0 浏览量 回答数 0

回答

"EnumSet类没有暴露任何构造器来创建该类的实例,程序应该通过它提供的static方法来创建EnumSet对象。EnumSet类它提供了如下常用的static方法来创建EnumSet对象。 static EnumSet allOf(Class elementType):创建一个包含指定枚举类里所有枚举值的EnumSet集合。 static EnumSet complementOf(EnumSet s):创建一个其元素类型与指定EnumSet里元素类型相同的EnumSet集合,新EnumSet集合包含原EnumSet集合所不包含的、此枚举类剩下的枚举值(即新EnumSet集合和原EnumSet集合的集合元素加起来就是该枚举类的所有枚举值)。 static EnumSet copyOf(Collection c):使用一个普通集合来创建EnumSet集合。 static EnumSet copyOf(EnumSet s):创建一个与指定EnumSet具有相同元素类型、相同集合元素的EnumSet集合。 static EnumSet noneOf(Class elementType):创建一个元素类型为指定枚举类型的空EnumSet。 static EnumSet of(E first,E...rest):创建一个包含一个或多个枚举值的EnumSet集合,传入的多个枚举值必须属于同一个枚举类。 static EnumSet range(E from,E to):创建一个包含从from枚举值到to枚举值范围内所有枚举值的EnumSet集合。"

星尘linger 2020-04-12 00:05:22 0 浏览量 回答数 0

回答

从Swift 2开始,这可以通过协议扩展方法来实现。 如果集合的元素为:,则将其removeObject()定义为对所有符合RangeReplaceableCollectionType(特别是Array)的类型的方法Equatable: extension RangeReplaceableCollectionType where Generator.Element : Equatable { // Remove first collection element that is equal to the given `object`: mutating func removeObject(object : Generator.Element) { if let index = self.indexOf(object) { self.removeAtIndex(index) } } } 例: var ar = [1, 2, 3, 2] ar.removeObject(2) print(ar) // [1, 3, 2] 更新斯威夫特2 / Xcode的7测试版2:空速速度在评论中发现,现在其实可以写一个通用的类型,它是在模板更严格的方法,因此该方法可现在居然被定义为一个扩展的Array: extension Array where Element : Equatable { // ... same method as above ... } 协议扩展仍然具有适用于更大类型集的优点。 Swift 3更新: extension Array where Element: Equatable { // Remove first collection element that is equal to the given `object`: mutating func remove(object: Element) { if let index = index(of: object) { remove(at: index) } } }

保持可爱mmm 2020-02-07 00:48:59 0 浏览量 回答数 0

回答

使用通用方法的解决方案 将通用方法定义为 public static <T> List<T> convertGeneric(List<List<Object>> dataframe, Function<Object, T> converter) 也就是说,第一个参数是您的对象集合,第二个参数是您提供从Object到目标类的转换函数。该方法返回一个List 。(请注意, 之后static需要声明一个通用方法。 该方法的实现可以是 List<T> result = new ArrayList<>(); for (List<Object> objects : dataframe) { for (Object object : objects) { T t = converter.apply(object); result.add(t); } } return result; } 或使用流的另一个: public static <T> List<T> convertGeneric(List<List<Object>> dataframe, Function<Object, T> converter) { return dataframe.stream() .flatMap(Collection::stream) // get the objects from the inner list .map(converter) // convert object to T .collect(Collectors.toList()); // put everything in a new list } 转换功能可以实现为lambda,例如 Function<Object, Foo> fooLambda = object -> { Foo foo = new Foo(); // logic for mapping obj to foo return foo; }; 和转换List<List<Object>>到List<Foo>变为: List<Foo> fooList = GenericMethodConverter.convertGeneric(dataFrame, fooLambda); 我认为您为这个问题而苦苦挣扎的原因是,您试图在通用方法中进行所有操作(抽象和具体部分)。您已经知道,泛型方法随后需要其他信息才能使用哪种具体实现(在您的版本中,将转换的目标类型作为第二个参数传递)。在上述解决方案中,通用方法需要转换函数Function<Object,T>,即将对象映射到目标类型T的函数。通用方法将此函数应用于所有对象,并将结果放入返回的列表中。用于映射的具体实现object为Foo作为从而reifying通用lambda表达式被供给T到Foo。可以根据需要添加其他转换功能。 另一种方法 这是使用面向对象/类而不是静态方法的解决方案: 定义一个抽象基类GenericConverter,其中包含要遍历列表的迭代,并声明一个抽象方法如何将an转换Object为目标类型: public abstract class GenericConverter<T> { public List<T> convertGenerically(List<List<Object>> dataFrame) { List<T> tList = new ArrayList<>(); for (List<Object> objectList : dataFrame) { for (Object obj : objectList) { T t = convert(obj); tList.add(t); } } return tList; } protected abstract T convert(Object obj); } 为每个目标类添加一个实现,例如,转换Object为Foo: public class FooConverter extends GenericConverter<Foo> { @Override protected Foo convert(Object obj) { Foo foo = new Foo(); // logic for mapping obj to foo return foo; } } 然后Objects通过调用实现类的方法来转换: List<Foo> foos = fooConverter.convertGenerically(dataFrame); 回答来源:Stack Overflow

montos 2020-03-24 17:52:36 0 浏览量 回答数 0

回答

可以通过mpserverless.db对象调用数据存储相关的API,也可以通过云函数直接调用同一个云服务的数据存储服务。 SDK调用示例 以下代码展示了如何通过小程序SDK获得当前云服务中todos集合内所有任务的列表: mpserverless.db.collection('todos').find().then((res) => { this.setData({ todos: res.result }); }).catch(console.error);

南霸天霸南北 2020-02-17 17:28:01 0 浏览量 回答数 0

回答

DriverMain课程是否覆盖了equals方法?” ... 为了使用(Array)List,HashTable,HashSet或HashMap等,需要在类中重写“一对”方法DriverMain。为了使List,Set等以及其他一些Collection Type或Map / HashTable评估你的对象是否是其内容的成员,你需要为其提供一种比较传递给它的对象和这些对象的方法。 列出 的contains(Object o)方法使用该对象的equals(Object o)方法,你的比较对象的o任何对象x(名单收集的成员)。 有关此的更多信息,请访问以下链接:https : //docs.oracle.com/javase/tutorial/java/IandI/objectclass.html https://docs.oracle.com/javase/tutorial/collections /interfaces/list.html 设置 的contains(Object o)方法使用该对象的hashCode()和equals(Object o)方法,以你的比较对象的o任何对象x(设置集合的成员)。 有关此的更多信息,请访问以下链接:https : //docs.oracle.com/javase/tutorial/java/IandI/objectclass.html https://docs.oracle.com/javase/tutorial/collections /interfaces/set.html Map 该containsKey(Object o)方法使用Object的hashCode()和equals(Object o)方法将你的Object o与任何Object x(Map Interface的成员)进行比较。 有关此的更多信息,请访问以下链接:https : //docs.oracle.com/javase/tutorial/java/IandI/objectclass.html https://docs.oracle.com/javase/tutorial/collections /interfaces/map.html 重要说明 解决这种情况的方法更多,具体取决于其实现方式。例如:TreeSet并且TreeMap不使用该hashCode()方法。

一码平川MACHEL 2019-12-02 02:19:40 0 浏览量 回答数 0

回答

Set是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。 Set接口主要实现了两个实现类:HashSet: HashSet类按照哈希算法来存取集合中的对象,存取速度比较快 TreeSet :TreeSet类实现了SortedSet接口,能够对集合中的对象进行排序。 List的特征是其元素以线性方式存储,集合中可以存放重复对象。 ArrayList() : 代表长度可以改变得数组。可以对元素进行随机的访问,向ArrayList()中插入与删除元素的速度慢。 LinkedList(): 在实现中采用链表数据结构。插入和删除速度快,访问速度慢。 Map 是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。 Map没有继承于Collection接口 从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。 HashMap:Map基于散列表的实现。插入和查询“键值对”的开销是固定的。可以通过构造器设置容量capacity和负载因子load factor,以调整容器的性能。 LinkedHashMap: 类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一点。而在迭代访问时发而更快,因为它使用链表维护内部次序。 TreeMap : 基于红黑树数据结构的实现。查看“键”或“键值对”时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap的特点在 于,你得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。 WeakHashMao :弱键(weak key)Map,Map中使用的对象也被允许释放: 这是为解决特殊问题设计的。如果没有map之外的引用指向某个“键”,则此“键”可以被垃圾收集器回收。

游客bnlxddh3fwntw 2020-04-10 14:16:43 0 浏览量 回答数 0

回答

当我可以在60秒内在类似硬件上执行相同操作时,您的查询要花2个小时才能执行,这是一件非常错误的事情。 以下某些内容可能会有所帮助... 为您的引擎调整MySQL 检查服务器配置并进行相应优化。以下某些资源应该是有用的。 http://www.mysqlperformanceblog.com/2006/09/29/what-to-tune-in-mysql-server-after-installation/ http://www.mysqlperformanceblog.com/ http://www.highperfmysql.com/ http://forge.mysql.com/wiki/ServerVariables http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html http://www.xaprb.com/blog/2006/07/04/how-to-exploit-mysql-index-optimizations/ http://jpipes.com/presentations/perf_tuning_best_practices.pdf http://jpipes.com/presentations/index_coding_optimization.pdf http://www.jasny.net/?p=36 现在不那么明显了... 考虑使用存储过程来处理数据服务器端 为什么不处理MySQL内部的所有数据,从而不必将大量数据发送到应用程序层?以下示例使用游标在2分钟内循环和处理服务器端5000万行。我不是游标的忠实拥护者,尤其是在MySQL游标非常有限的地方,但是我猜想您会循环结果集并进行某种形式的数值分析,因此在这种情况下使用游标是合理的。 简化的myisam结果表-基于您的密钥。 drop table if exists results_1mregr_c_ew_f; create table results_1mregr_c_ew_f ( id int unsigned not null auto_increment primary key, rc tinyint unsigned not null, df int unsigned not null default 0, val double(10,4) not null default 0, ts timestamp not null default now(), key (rc, df) ) engine=myisam; 我生成了1亿行数据,其中关键字段的基数与您的示例大致相同: show indexes from results_1mregr_c_ew_f; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Index_type ===== ========== ======== ============ =========== ========= =========== ========== results_1mregr_c_ew_f 0 PRIMARY 1 id A 100000000 BTREE results_1mregr_c_ew_f 1 rc 1 rc A 2 BTREE results_1mregr_c_ew_f 1 rc 2 df A 223 BTREE 存储过程 我创建了一个简单的存储过程,该过程将获取所需的数据并对其进行处理(使用与示例相同的where条件) drop procedure if exists process_results_1mregr_c_ew_f; delimiter # create procedure process_results_1mregr_c_ew_f ( in p_rc tinyint unsigned, in p_df int unsigned ) begin declare v_count int unsigned default 0; declare v_done tinyint default 0; declare v_id int unsigned; declare v_result_cur cursor for select id from results_1mregr_c_ew_f where rc = p_rc and df > p_df; declare continue handler for not found set v_done = 1; open v_result_cur; repeat fetch v_result_cur into v_id; set v_count = v_count + 1; -- do work... until v_done end repeat; close v_result_cur; select v_count as counter; end # delimiter ; 观察到以下运行时: call process_results_1mregr_c_ew_f(0,60); runtime 1 = 03:24.999 Query OK (3 mins 25 secs) runtime 2 = 03:32.196 Query OK (3 mins 32 secs) call process_results_1mregr_c_ew_f(1,60); runtime 1 = 04:59.861 Query OK (4 mins 59 secs) runtime 2 = 04:41.814 Query OK (4 mins 41 secs) counter 23000002 (23 million rows processed in each case) 嗯,性能有些令人失望,因此进入下一个想法。 考虑使用innodb引擎(令人震惊的恐怖) 为什么是innodb?因为它具有聚簇索引!您会发现使用innodb的插入速度较慢,但​​希望读取速度会更快,因此这是值得的折衷选择。 通过聚集索引访问行的速度很快,因为行数据位于索引搜索所位于的同一页上。如果表很大,则与使用不同于索引记录的页面存储行数据的存储组织相比,聚集索引体系结构通常可以节省磁盘I / O操作。例如,MyISAM将一个文件用于数据行,将另一个文件用于索引记录。 更多信息在这里: http://dev.mysql.com/doc/refman/5.0/en/innodb-index-types.html 简化的innodb结果表 drop table if exists results_innodb; create table results_innodb ( rc tinyint unsigned not null, df int unsigned not null default 0, id int unsigned not null, -- cant auto_inc this !! val double(10,4) not null default 0, ts timestamp not null default now(), primary key (rc, df, id) -- note clustered (innodb only !) composite PK ) engine=innodb; innodb的一个问题是它不支持构成复合键一部分的auto_increment字段,因此您必须自己使用序列生成器,触发器或其他方法(可能是在填充结果表本身的应用程序中)提供递增的键值?? 同样,我生成了1亿行数据,这些键字段的基数与您的示例大致相同。如果这些数字与myisam示例不匹配,请不要担心,因为innodb估计基数,因此它们不会完全相同。(但它们-使用相同的数据集) show indexes from results_innodb; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Index_type ===== ========== ======== ============ =========== ========= =========== ========== results_innodb 0 PRIMARY 1 rc A 18 BTREE results_innodb 0 PRIMARY 2 df A 18 BTREE results_innodb 0 PRIMARY 3 id A 100000294 BTREE 存储过程 存储过程与上面的myisam示例完全相同,但是从innodb表中选择数据。 declare v_result_cur cursor for select id from results_innodb where rc = p_rc and df > p_df; 结果如下: call process_results_innodb(0,60); runtime 1 = 01:53.407 Query OK (1 mins 53 secs) runtime 2 = 01:52.088 Query OK (1 mins 52 secs) call process_results_innodb(1,60); runtime 1 = 02:01.201 Query OK (2 mins 01 secs) runtime 2 = 01:49.737 Query OK (1 mins 50 secs) counter 23000002 (23 million rows processed in each case) 比myisam引擎实施快约2-3分钟!(innodb FTW) 分而治之 在使用游标的服务器端存储过程中处理结果可能不是最佳解决方案,尤其是因为MySQL不支持诸如数组和复杂数据结构之类的东西,而这些东西在3GL语言(如C#等)或什至在其他数据库(如作为Oracle PL / SQL。 因此,这里的想法是将成批的数据返回到应用程序层(C#等),然后可以将结果添加到基于集合的数据结构中,然后在内部处理数据。 存储过程 该存储过程需要3个参数rc,df_low和df_high,这使您可以选择以下数据范围: call list_results_innodb(0,1,1); -- df 1 call list_results_innodb(0,1,10); -- df between 1 and 10 call list_results_innodb(0,60,120); -- df between 60 and 120 etc... 显然,df范围越高,您将提取的数据越多。 drop procedure if exists list_results_innodb; delimiter # create procedure list_results_innodb ( in p_rc tinyint unsigned, in p_df_low int unsigned, in p_df_high int unsigned ) begin select rc, df, id from results_innodb where rc = p_rc and df between p_df_low and p_df_high; end # delimiter ; 我还敲出了一个myisam版本,除了所使用的表外,该版本完全相同。 call list_results_1mregr_c_ew_f(0,1,1); call list_results_1mregr_c_ew_f(0,1,10); call list_results_1mregr_c_ew_f(0,60,120); 基于上面的光标示例,我希望innodb版本的性能优于myisam版本。 我开发了一个快速且肮脏的多线程C#应用程序,该应用程序将调用存储过程并将结果添加到集合中以进行后查询处理。您不必使用线程,可以按顺序完成相同的批处理查询方法,而不会造成性能损失。 每个线程(QueryThread)选择一个df数据范围,循环结果集,并将每个结果(行)添加到结果集合中。 class Program { static void Main(string[] args) { const int MAX_THREADS = 12; const int MAX_RC = 120; List<AutoResetEvent> signals = new List<AutoResetEvent>(); ResultDictionary results = new ResultDictionary(); // thread safe collection DateTime startTime = DateTime.Now; int step = (int)Math.Ceiling((double)MAX_RC / MAX_THREADS) -1; int start = 1, end = 0; for (int i = 0; i < MAX_THREADS; i++){ end = (i == MAX_THREADS - 1) ? MAX_RC : end + step; signals.Add(new AutoResetEvent(false)); QueryThread st = new QueryThread(i,signals[i],results,0,start,end); start = end + 1; } WaitHandle.WaitAll(signals.ToArray()); TimeSpan runTime = DateTime.Now - startTime; Console.WriteLine("{0} results fetched and looped in {1} secs\nPress any key", results.Count, runTime.ToString()); Console.ReadKey(); } } 运行时观察如下: Thread 04 done - 31580517 Thread 06 done - 44313475 Thread 07 done - 45776055 Thread 03 done - 46292196 Thread 00 done - 47008566 Thread 10 done - 47910554 Thread 02 done - 48194632 Thread 09 done - 48201782 Thread 05 done - 48253744 Thread 08 done - 48332639 Thread 01 done - 48496235 Thread 11 done - 50000000 50000000 results fetched and looped in 00:00:55.5731786 secs Press any key 因此,在不到60秒的时间内获取了5000万行并将其添加到集合中。 我使用myisam存储过程尝试了同样的事情,该过程花了2分钟才能完成。 50000000 results fetched and looped in 00:01:59.2144880 secs 移至innodb 在我的简化系统中,myisam表的性能不会太差,因此可能不值得迁移到innodb。如果您确实决定将结果数据复制到innodb表中,请按照以下步骤进行操作: start transaction; insert into results_innodb select <fields...> from results_1mregr_c_ew_f order by ; commit; 在将整个事物插入并包装到事务中之前,通过innodb PK对结果进行排序将加快速度。 我希望其中一些证明是有帮助的。 祝好运

保持可爱mmm 2020-05-18 11:14:35 0 浏览量 回答数 0

回答

注意此时调用的是方法add,这里实现了多态,调用的是具体实现类里的add方法,也就是你hashset的实现的add方法 PleaseAdd 引用代码的正确姿势如下,你用的是常规引用,显示有问题。<preclass="brush:java;toolbar:true;auto-links:false;">publicbooleanaddAll(Collection<?extendsE>c){booleanmodified=false;Iterator<?extendsE>e=c.iterator();while(e.hasNext()){if(add(e.next()))modified=true;}returnmodified;} <spanstyle="line-height:1.5;font-size:10pt;">上面的变量e,集合c的迭代器,用于遍历操作。 <spanstyle="line-height:1.5;font-size:10pt;"><spanstyle="font-size:13.3333px;">循环体的条件是:只要后面还有元素,就继续 e.next()就是在这个集合里取值(取的是下一个元素) 所以,add(e.next())就是将集合成员一个一个添加进去的操作。 它判断的不是“c中每一个值是否会报错”,而是检查对每一个值的添加操作是否出错。 <spanstyle="color:<atarget='_blank'>#808080;background-color:#e2ffe2;font-style:italic;"><p><spanstyle="color:#808080;font-style:italic;">Notethatthisimplementationwillthrowan<spanstyle="color:#808080;font-style:italic;">*<spanstyle="color:<atarget='_blank'>#808080;background-color:#e2ffe2;font-style:italic;"><tt><spanstyle="color:#808080;font-style:italic;">UnsupportedOperationException<spanstyle="color:#808080;background-color:#e2ffe2;font-style:italic;"></tt><spanstyle="color:#808080;font-style:italic;">unless<spanstyle="color:<atarget='_blank'>#808080;background-color:#e2ffe2;font-style:italic;"><tt><spanstyle="color:#808080;font-style:italic;">add<spanstyle="color:#808080;background-color:#e2ffe2;font-style:italic;"></tt><spanstyle="color:#808080;font-style:italic;">is<spanstyle="color:#808080;font-style:italic;">*overridden(assumingthespecifiedcollectionisnon-empty).

爱吃鱼的程序员 2020-06-10 13:29:36 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站