哦,那些棘手的Java 8流与lambdas.它们非常强大,但错综复杂需要一点点围绕它的所有.
假设我有User一个属性类型User.getName().假设我有一个Map<String, User>与名称相关联的用户的地图(例如,登录用户名).让我们进一步说,我有一个比较器的实例UserNameComparator.INSTANCE来排序用户名(可能与花哨的合作者等).
那么如何获取地图中的用户列表,按用户名排序?我可以忽略地图键并执行此操作:
return userMap.values()
.stream()
.sorted((u1, u2) -> {
return UserNameComparator.INSTANCE.compare(u1.getName(), u2.getName());
})
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
但是,我必须提取名称以使用的那一行UserNameComparator.INSTANCE似乎太多的手工工作.有什么方法我可以简单地提供User::getName一些映射函数,只是为了排序,并仍然将User实例返回到收集列表中?
额外奖励:如果我想要排序的东西是两个层次,如User.getProfile().getUsername()?
任何Java 8 + JDBC专家都能告诉我以下推理是否有问题吗?而且,如果在神的秘密中,为什么没有这样做?
A java.sql.Date当前是JDBC用于映射到DATE SQL类型的类型,它表示没有时间且没有时区的日期.但是这个类设计得非常好,因为它实际上是一个子类java.util.Date,它可以存储精确的瞬间,最长可达毫秒.
为了在数据库中表示日期2015-09-13,我们因此被迫选择一个时区,在该时区中将字符串"2015-09-13T00:00:00.000"解析为java.util.Date以获得毫秒value,然后java.sql.Date从这个毫秒值构造一个,最后调用setDate()预准备语句,传递一个包含所选时区的Calendar,以便JDBC驱动程序能够从这个毫秒值正确地重新计算日期2015-09-13.通过在任何地方使用默认时区,而不是传递日历,可以使此过程更简单一些.
Java 8引入了一个LocalDate类,它更适合DATE数据库类型,因为它不是精确的时刻,因此不依赖于时区.Java 8还引入了默认方法,这些方法允许对PreparedStatement和ResultSet接口进行向后兼容的更改.
那么,我们还没有错过一个清理JDBC中的混乱的大好机会,同时仍然保持向后兼容性?Java 8可以简单地将这些默认方法添加到PreparedStatement和ResultSet:
default public void setLocalDate(int parameterIndex, LocalDate localDate) {
if (localDate == null) {
setDate(parameterIndex, null);
}
else {
ZoneId utc = ZoneId.of("UTC");
java.util.Date utilDate = java.util.Date.from(localDate.atStartOfDay(utc).toInstant());
Date sqlDate = new Date(utilDate.getTime());
setDate(parameterIndex, sqlDate, Calendar.getInstance(TimeZone.getTimeZone(utc)));
}
}
default LocalDate getLocalDate(int parameterIndex) {
ZoneId utc = ZoneId.of("UTC");
Date sqlDate = getDate(parameterIndex, Calendar.getInstance(TimeZone.getTimeZone(utc)));
if (sqlDate == null) {
return null;
}
java.util.Date utilDate …Run Code Online (Sandbox Code Playgroud) 在Java中,可以轻松地生成无限流Stream.generate(supplier).但是,我需要生成一个最终完成的流.
想象一下,例如,我想要一个目录中所有文件的流.文件数量可能很大,因此我无法预先收集所有数据并从中创建流(via collection.stream()).我需要逐个生成序列.但是流很明显会在某个时刻完成,终端运营商喜欢(collect()或findAny())需要对它进行处理,因此Stream.generate(supplier)不适合这里.
有没有合理的简单方法在Java中执行此操作,而不是自己实现整个Stream接口?
我可以想到一个简单的黑客 - 用无限做它Stream.generate(supplier),并在获取所有实际值时提供null或抛出异常.但是它会破坏标准的流操作符,我只能将它用于我自己的操作符,这些操作符都知道这种行为.
澄清
评论中的人提议我takeWhile()操作员.这不是我的意思.如何更好地表达问题...我不是在问如何过滤(或限制)现有的流,我问如何动态创建(生成)流,而不是先加载所有元素,但是流会有有限的大小(事先未知).
解
我正在寻找的代码是
Iterator it = myCustomIteratorThatGeneratesTheSequence();
StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), false);
Run Code Online (Sandbox Code Playgroud)
我刚看了一下java.nio.file.Files,该list(path)方法是如何实现的.
为什么我不能@FunctionalInterface使用默认方法实现创建?
@FunctionalInterface
public interface MyInterface {
default boolean authorize(String value) {
return true;
}
}
Run Code Online (Sandbox Code Playgroud) 我试图找到intersection两个基于某些条件并执行一些步骤的列表.找不到办法(在学习阶段):)
Double totalAmount = 0.00d;
Double discount = 0.00d;
List<OrderLineEntry> orderLineEntryList = orderEntry.getOrderReleases().stream()
.flatMap(orderReleaseEntry -> orderReleaseEntry.getOrderLines().stream())
.filter(orderLineEntry -> orderLineEntry.getStatus().equals("PP") || orderLineEntry.getStatus().equals("PD"))
.collect(Collectors.toList());
for (OrderLineEntry orderLineEntry : orderLineEntryList) {
for (SplitLineEntry splitLineEntry : splitReleaseEntry.getLineEntries()) {
if (splitLineEntry.getOrderLineId().equals(orderLineEntry.getId()) && splitLineEntry.getStatusCode() != "PX") {
totalAmount += orderLineEntry.getFinalAmount();
couponDiscount += orderLineEntry.getCouponDiscount() == null ? 0.00d : orderLineEntry.getCouponDiscount();
}
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,逻辑很简单
根据一些过滤器从订单获取所有项目list并与另一个过滤list并做一些事情.
在我的测试用例中,我需要测试时间敏感的方法,在那个方法中我们使用的是java 8类的LocalDate,它不是Joda.
当我正在进行测试时,我可以做些什么来改变时间
流中是否有sum()等效方法,可以执行流中给出的值的乘法?
我有一个像这样的整数列表:
List<Integer> listOfIntegers = new ArrayList<>();
listOfIntegers.addAll(Arrays.asList(1,4,2,7,5));
Run Code Online (Sandbox Code Playgroud)
我能够得到所有整数的总和,但无法找到可以乘以值并给出输出的API.
listOfIntegers.stream().mapToInt(a -> a).sum();
Run Code Online (Sandbox Code Playgroud)
如果我尝试使用forEach来执行此操作,那么我无法存储结果,因为只允许在其中使用最终变量.
有没有替代方案?
我Fruit在arraylist中有一个对象列表,我想将fruitName修改为其复数名称.参考示例:
@Data
@AllArgsConstructor
@ToString
class Fruit {
long id;
String name;
String country;
}
List<Fruit> fruits = Lists.newArrayList();
fruits.add(new Fruit(1L, "Apple", "India"));
fruits.add(new Fruit(2L, "Pineapple", "India"));
fruits.add(new Fruit(3L, "Kiwi", "New Zealand"));
Comparator<Option> byNameComparator = (e1, e2) -> e1.getName().compareToIgnoreCase(e2.getName());
fruits = fruits.stream().filter(fruit -> "India".equals(fruit.getCountry()))
.sorted(byNameComparator).collect(Collectors.toList());
List<Fruit> fruitsWithPluralNames = Lists.newArrayList();
for (Fruit fruit : fruits) {
fruit.setName(fruit.getName() + "s");
fruitsWithPluralNames.add(fruit);
}
System.out.println(fruitsWithPluralNames);
// which prints [Fruit(id=1, name=Apples, country=India), Fruit(id=2, name=Pineapples, country=India), Fruit(id=3, name=Kiwis, country=New Zealand)]
Run Code Online (Sandbox Code Playgroud)
我们有没有办法使用java8流实现相同的行为?
正在使用的技术堆栈:
Java 8 MapStruct:1.2.0.Final Lombok:1.16.18 IDE:IntelliJ - 已经安装了Lombok插件
@Getter和@Setter注释时,我遇到了问题,mapstruct无法找到属性并说:Unknown property "id" in result type com.vg.once.dto.OneDto. Did you mean "null"?以下是项目文件:
实体对象:One.java:
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class One {
private int id;
private Integer version;
private int projectId;
private String title;
private String code;
private int sortOrder;
}
Run Code Online (Sandbox Code Playgroud)
DTO对象:OneDTO.java:
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class OneDto {
private int id;
private …Run Code Online (Sandbox Code Playgroud) intellij-idea lombok java-8 mapstruct intellij-lombok-plugin
这是来自Oracle的JDK 8实现的Stream接口:
public interface Stream<T> extends BaseStream<T, Stream<T>> {
Stream<T> sorted();
}
Run Code Online (Sandbox Code Playgroud)
并且很容易在运行时将其清除,并且在编译时不会生成警告.这是一个例子:
class Foo {
public static void main(String[] args) {
Arrays.asList(new Foo(), new Foo()).stream().sorted().forEach(f -> {});
}
}
Run Code Online (Sandbox Code Playgroud)
这将编译得很好,但会在运行时抛出异常:
Exception in thread "main" java.lang.ClassCastException: Foo cannot be cast to java.lang.Comparable
Run Code Online (Sandbox Code Playgroud)
sorted在编译器实际可以捕获这些问题的地方没有定义该方法的原因是什么?也许我错了,但不是这么简单:
interface Stream<T> {
<C extends Comparable<T>> void sorted(C c);
}
Run Code Online (Sandbox Code Playgroud)
?
显然,那些实现这一点的人(考虑到编程和工程方面比我早了几年)必须有一个很好的理由,我无法看到,但这是什么原因?
java-8 ×10
java ×8
java-stream ×5
lambda ×2
comparable ×1
date ×1
intersection ×1
java-time ×1
jdbc ×1
lombok ×1
mapstruct ×1
sorting ×1
systemtime ×1