我想学习如何使用Java 8语法与流,并有点卡住.
当你为每个值都有一个键时,很容易分组.但是如果我为每个值都有一个键列表并且仍然想用groupingBy对它们进行分类呢?我是否必须将其分解为多个语句,或者可能有一些流魔术可以使其更简单.
这是基本代码:
List<Album> albums = new ArrayList<>();
Map<Artist, List<Album>> map = albums.stream().collect(Collectors.groupingBy(this::getArtist));
Run Code Online (Sandbox Code Playgroud)
如果每个专辑只有一个艺术家,那么效果很好.但我必须返回一个列表,因为专辑可以有很多艺术家.专辑和艺术家当然用于说明,我有真实世界的类型..
可能有一个简单的解决方案,但我有一段时间没有找到它,所以我呼吁这个网站代表的集体大脑来解决它.:)如果不存在简单的解决方案,也欢迎使用复杂的解决方案.
在Album类中或作为以Album作为参数的实用程序方法:
Artist getArtist(); // ok
List<Artist> getArtist(); // Not ok, since we now have many "keys" for every Album
Run Code Online (Sandbox Code Playgroud)
干杯,Mikael Grev
我在流上调用已排序的方法.而且java doc说:
"Sorted方法返回一个由该流的元素组成的流,按照自然顺序排序."
但是当我运行下面的代码时:
List<String> list = new ArrayList<String>();
list.add("b");
list.add("a");
list.add("z");
list.add("p");
list.stream().sorted();
System.out.println(list);
Run Code Online (Sandbox Code Playgroud)
我得到输出为
[b, a, z, p]
Run Code Online (Sandbox Code Playgroud)
为什么我没有获得自然排序的输出?
对于我的具体任务,我需要将数据读取FileChannel到Stream(或Collection)String的.
在常规NIO中Path我们可以使用方便的方法Files.lines(...)返回一个Stream<String>.我需要得到相同的结果,但是从而FileChannel不是Path:
public static Stream<String> lines(final FileChannel channel) {
//...
}
Run Code Online (Sandbox Code Playgroud)
任何想法如何做到这一点?
正如在这个问题中所讨论的那样,distinct()当运行它的流被运行时知道时,实现能够使用更有效的算法.如果我们知道流是排序的(例如,因为它来自外部预先排序的数据源,例如带有order by子句的SQL查询)但是没有标记为这样,我们如何才能获得类似的结果?有一个unordered()操作可以删除排序标志,但据我所知,没有办法告诉系统数据是在外部排序的.
是否可以在mapToObj方法中执行多个语句?.假设我想使用以下代码将字符串转换为二进制字符串:
String str = "hello";
String bin = str.chars()
.mapToObj(x-> Integer.toBinaryString(x))
.collect(Collectors.joining(" "));
Run Code Online (Sandbox Code Playgroud)
但是,我想使用类似的东西处理前导零
String.format("%8s", x).replaceAll(" ", "0")
Run Code Online (Sandbox Code Playgroud)
那么,如何在mapToObj方法中添加它.我是Java 8新功能的新手.任何帮助,将不胜感激
我正在研究一些处理多个REST调用的java代码
call1()
call2()
call3()
...
Run Code Online (Sandbox Code Playgroud)
我希望并行化这些调用,但同步执行我的主代码.我用lamba和并行流做了一个POC:
List<Runnable> list = new ArrayList();
list.add(() -> {call1()});
list.add(() -> {call2()});
list.add(() -> {call3()});
list.add(...);
list.parallelStream()
.forEach(Runnable::run);
Run Code Online (Sandbox Code Playgroud)
你有其他解决方案吗?我还检查过使用来自Jersey客户端的异步调用,但这需要更多的代码更改.
我想转换:
Map<String, Map<String, List<Map<String, String>>>> inputMap
Run Code Online (Sandbox Code Playgroud)
到:
Map<String, Map<String, CustomObject>> customMap
Run Code Online (Sandbox Code Playgroud)
inputMap在配置中提供并准备就绪,但我需要customMap格式化。CustomObject 将通过List<Map<String, String>>在函数中使用几行代码来派生。
我已经尝试了迭代输入映射和复制 customMap 中的键值的正常方法。有没有使用 Java 8 或其他一些快捷方式来做到这一点的有效方法?
Map<String, Map<String, List<Map<String, String>>>> configuredMap = new HashMap<>();
Map<String, Map<String, CustomObj>> finalMap = new HashMap<>();
for (Map.Entry<String, Map<String, List<Map<String, String>>>> attributeEntry : configuredMap.entrySet()) {
Map<String, CustomObj> innerMap = new HashMap<>();
for (Map.Entry<String, List<Map<String, String>>> valueEntry : attributeEntry.getValue().entrySet()) {
innerMap.put(valueEntry.getKey(), getCustomeObj(valueEntry.getValue()));
}
finalMap.put(attributeEntry.getKey(), innerMap);
}
private CustomObj getCustomeObj(List<Map<String, String>> list) {
return new CustomObj();
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 Java StreamsString从我的列表中收集最大长度的所有s:
List<String> strings = Arrays.asList("long word", "short", "long wwww", "llll wwww", "shr");
List<String> longest = strings.stream()
.sorted(Comparator.comparingInt(String::length).reversed())
.takeWhile(???)
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
我希望 mylongest包含{"long word", "long wwww", "llll wwww"},因为那些是String具有最大长度的s。如果只有String最大长度的s之一,我显然希望结果List只包含该元素。
我试图首先对它们进行排序,以便在第一个元素中出现最大长度,但我无法检索流中第一个元素的长度。我可以尝试类似的东西peek():
static class IntWrapper {
int value;
}
public static void main(String[] args) throws IOException {
List<String> strings = Arrays.asList("long word", "short", "long wwww", "llll wwww", "shr");
IntWrapper wrapper = new IntWrapper();
List<String> longest = strings.stream()
.sorted(Comparator.comparingInt(String::length).reversed())
.peek(s …Run Code Online (Sandbox Code Playgroud) parallel()然而,今天我使用的是在地图之后执行操作的流;底层源是一个非线程安全的迭代器,类似于BufferedReader.lines实现。
我原本以为 trySplit 会在创建的线程上调用,但是;我观察到对迭代器的访问来自多个线程。
例如,以下愚蠢的迭代器实现只是设置了足够的元素来导致分裂,并且还跟踪访问该hasNext方法的唯一线程。
class SillyIterator implements Iterator<String> {
private final ArrayDeque<String> src =
IntStream.range(1, 10000)
.mapToObj(Integer::toString)
.collect(toCollection(ArrayDeque::new));
private Map<String, String> ts = new ConcurrentHashMap<>();
public Set<String> threads() { return ts.keySet(); }
private String nextRecord = null;
@Override
public boolean hasNext() {
var n = Thread.currentThread().getName();
ts.put(n, n);
if (nextRecord != null) {
return true;
} else {
nextRecord = src.poll();
return nextRecord != null;
}
}
@Override
public String next() {
if (nextRecord …Run Code Online (Sandbox Code Playgroud) 单元测试的问题是同一集合在流和 for 循环中的处理方式不同。两种情况下的集合都是空的(data.size() = 0),但在情况 1 中,该集合以某种方式进行了处理,换句话说,它将进入 for 循环。在情况 2 中,该集合只是被跳过(这是预期的,因为它是空的)。
测试使用 Mockito,并将Result<Record>用于 JOOQ。
测试是旧的并且没有变化,唯一的变化是从 for 循环到流。
情况1
private SearchResult iterateData(
Result<Record> data, ...) {
for (Record record : data) {
doSomething(record);
}
Run Code Online (Sandbox Code Playgroud)
案例2
private SearchResult iterateData(
Result<Record> data, ...) {
data.stream().forEach(record -> doSomething(record));
Run Code Online (Sandbox Code Playgroud)
案例 1 for 循环示例的屏幕截图
模拟结果对象
private DefaultSearchRequestModel rowSpecificValuesTestSetup(
parameters...) {
DefaultSearchRequestModel searchRequest = new DefaultSearchRequestModel(
Arrays.asList(....),
Collections.singletonList(
new SearchFilter(
"test",
Collections.singletonList(...)));
List<Column> columns =
this.searchService.filterUserAllowedColumns(...);
Condition searchCondition =
this.searchRepositoryMock.getSearchConditions(...);
List<TableJoinMapping> joinMappings = …Run Code Online (Sandbox Code Playgroud) java-stream ×10
java ×9
java-8 ×5
collections ×1
grouping ×1
jooq ×1
mapreduce ×1
mockito ×1
nio ×1
performance ×1
rest ×1
sorting ×1