我经常遇到Java lambda表达式的问题,当我想在对象的任意属性或方法上使用distinct()一个流时,但想要保留对象而不是将其映射到该属性或方法.我开始创建这里讨论的容器,但我开始做足够的事情,它变得烦人,并制作了很多样板类.
我将这个Pairing类放在一起,该类包含两个类型的两个对象,并允许您指定左,右或两个对象的键控.我的问题是......对于某些类型的关键供应商,distinct()是否真的没有内置的lambda流功能?那真让我感到惊讶.如果没有,该课程能否可靠地完成该功能?
以下是它的调用方式
BigDecimal totalShare = orders.stream().map(c -> Pairing.keyLeft(c.getCompany().getId(), c.getShare())).distinct().map(Pairing::getRightItem).reduce(BigDecimal.ZERO, (x,y) -> x.add(y));
Run Code Online (Sandbox Code Playgroud)
这是配对课程
public final class Pairing<X,Y> {
private final X item1;
private final Y item2;
private final KeySetup keySetup;
private static enum KeySetup {LEFT,RIGHT,BOTH};
private Pairing(X item1, Y item2, KeySetup keySetup) {
this.item1 = item1;
this.item2 = item2;
this.keySetup = keySetup;
}
public X getLeftItem() {
return item1;
}
public Y getRightItem() {
return item2;
}
public static <X,Y> Pairing<X,Y> keyLeft(X item1, Y item2) { …Run Code Online (Sandbox Code Playgroud) 想象一下,我有一些看起来像这样的东西:
Stream<Integer> stream = Stream.of(2,1,3,5,6,7,9,11,10)
.distinct()
.sorted();
Run Code Online (Sandbox Code Playgroud)
两者的javadocs distinct()并sorted()说它们是"有状态的中间操作".这是否意味着内部流将执行类似创建哈希集,添加所有流值,然后看到sorted()将这些值抛出到排序列表或排序集?或者它比那更聪明?
换句话说,是否.distinct().sorted()导致java遍历流两次或者java延迟直到执行终端操作(例如.collect)?
正如在这个问题中所讨论的那样,distinct()当运行它的流被运行时知道时,实现能够使用更有效的算法.如果我们知道流是排序的(例如,因为它来自外部预先排序的数据源,例如带有order by子句的SQL查询)但是没有标记为这样,我们如何才能获得类似的结果?有一个unordered()操作可以删除排序标志,但据我所知,没有办法告诉系统数据是在外部排序的.
这就是我在做的事情:
List scores = Stream.concat(oldEntries.stream(), newEntries.stream())
.sorted()
.distinct()
.limit(maxSize)
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
我期待一个没有任何重复的排序列表,但有时候列表中有重复.
我已经覆盖了hashCode和equals方法,我还观察到这些方法每次都返回正确的值.任何人都可以看到我的流有什么问题吗?
这是我的equals()和hashCode()它们由IDEA自动生成:
..
private int userId;
private int levelId;
private int score;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Score score = (Score) o;
if (userId != score.userId) return false;
return levelId == score.levelId;
}
@Override
public int hashCode() {
int result = userId;
result = 31 * result + levelId;
return result;
} …Run Code Online (Sandbox Code Playgroud) 方法将逗号分隔的单词作为a String并以逗号分隔的单词返回String自然排序顺序中的单词,不包含任何4个字母单词,包含UPPER大小写中的所有单词且不重复.与第二种方法相比,第一种方法相当慢.你能帮我理解为什么以及如何改进我的方法?
方法1:
public String stringProcessing(String s){
Stream<String> tokens = Arrays.stream(s.split(","));
return tokens.filter(t -> t.length() != 4) .distinct()
.sorted()
.collect(Collectors.joining(",")).toUpperCase();
}
Run Code Online (Sandbox Code Playgroud)
方法2:
public String processing(String s) {
String[] tokens = s.split(",");
Set<String> resultSet = new TreeSet<>();
for(String t:tokens){
if(t.length() != 4)
resultSet.add(t.toUpperCase());
}
StringBuilder result = new StringBuilder();
resultSet.forEach(key -> {
result.append(key).append(",");
});
result.deleteCharAt(result.length()-1);
return result.toString();
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试将我的流知识应用于一些 leetcode 算法问题。以下是问题的一般摘要:
给定一个只包含小写字母的字符串,删除重复的字母,使每个字母只出现一次。您必须确保您的结果在所有可能的结果中按字典顺序最小。
例子:
Input: "bcabc"
Output: "abc"
Run Code Online (Sandbox Code Playgroud)
另一个例子:
Input: "cbacdcbc"
Output: "acdb"
Run Code Online (Sandbox Code Playgroud)
这似乎是一个简单的问题,只需将值从字符串流式传输到新列表中,对值进行排序,找到不同的值,然后将其扔回列表中,并将列表的值附加到字符串中。这是我想出的:
public String removeDuplicateLetters(String s)
{
char[] c = s.toCharArray();
List<Character> list = new ArrayList<>();
for(char ch : c)
{
list.add(ch);
}
List<Character> newVal = list.stream().distinct().collect(Collectors.toList());
String newStr = "";
for(char ch : newVal)
{
newStr += ch;
}
return newStr;
}
Run Code Online (Sandbox Code Playgroud)
第一个示例运行良好,但第二个输出不是“acdb”,而是“abcd”。为什么 abcd 不是最小的字典顺序?谢谢!
每次当我接受编码面试时,我总是避免使用Java流,因为我不能很好地分析时间复杂度。
例如:在日常工作中,我可能会这样写:
Arrays.stream(a).distinct().sorted().toArray();
Run Code Online (Sandbox Code Playgroud)
获取唯一编号并对它们进行排序。
但我很好奇时间复杂度是......?is unique().sorted 会变成嵌套循环吗?
我需要把它们分开吗?
int[] arr = Arrays.stream(a).distinct().toArray();
Arrays.stream(arr).sorted().toArray();
Run Code Online (Sandbox Code Playgroud)
所以有时当我接受采访时,我会使用 set 来区分然后对它们进行排序......但我真的想编写一个干净的代码......
如果有人可以帮忙的话!谢谢你!
我有一个Answer类和一个User类.
答案有一个getUser()和用户有一个getPoints()
从答案列表中我想得到一个按点排序的用户哈希集.我试过以下:
Set<User> collectSet = list.stream().map(Answer::getUser)
.sorted(Comparator.comparing(User::getPoints))
.collect(Collectors.toCollection(HashSet::new));
collectSet.forEach(a -> System.out.println(a.toString()));
Run Code Online (Sandbox Code Playgroud)
不幸的是,这似乎没有保留顺序.输出总是不同的.
有趣的是,列表的相同示例可以正常工作
List<User> collectList = list.stream().map(Answer::getUser)
.sorted(Comparator.comparing(User::getPoints))
.collect(Collectors.toList());
collectList.forEach(a -> System.out.println(a.toString()));
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?