使用Java流过滤列表内容,仅保留与另一个列表的完整内容匹配的条目。

huangapple go评论72阅读模式
英文:

Filter contents of list with entries matching entire contents of another list Java streams

问题

我可能无法很好地搜索,但从理论上讲,这是一个简单的查询。我有一列包含数字的数组列表。我想要筛选与另一个列表中的所有条目都匹配的列表。

假设以下是我的列表:
{1,2,3},{1,2},{1},{2},{3},{2,3}

现在,如果我的条件列表是{1,2},我应该会得到以下结果:
{1,2,3},{1,2}

基本上,我正在寻找与条件列表的所有匹配项。我尝试使用谓词中的contains,但它返回类似于或条件的结果。

// 内部创建数组
products.add(new ProdData(344, 766));
products.add(new ProdData(344,123));
products.add(new ProdData(344,766,123));

List matchingVolumes = new ArrayList<>();
matchingVolumes.add(344);
matchingVolumes.add(766);

products.stream()
.map(ProdData::getChemVolume)
.filter(p -> {return matchingVolumes.contains(p);})
.collect(Collectors.toList());

我想要匹配记录#1和#3

products是ProdData对象的列表,其中chemVolume是我尝试匹配条件的字段。条目的顺序无关紧要。

英文:

I may be not able to search properly but this is a query in theory is simple. I have list of arrays containing numbers. I want to filter list which match all entries from another list.

Say following is my list
{1,2,3},{1,2},{1},{2},{3}, {2,3}

Now If my criteria list is {1,2} I should get following result
{1,2,3},{1,2}

Basically I am looking for all match for criteria list. I tried using contains in predicate but its returns like or condition

//internally it creates array 
products.add(new ProdData(344, 766));
products.add(new ProdData(344,123));
products.add(new ProdData(344,766,123));

List&lt;Integer&gt; matchingVolumes = new ArrayList&lt;&gt;();
    matchingVolumes.add(344);
    matchingVolumes.add(766);
    
products.stream()
   	.map(ProdData::getChemVolume)
   	.filter(p -&gt; {return matchingVolumes.contains(p);})
   	.collect(Collectors.toList());

I want to match records # 1 and 3

products is list of ProdData objects from which chemVolume is the field I am trying to match the criteria. Order of entries does not matter.

答案1

得分: 1

如果您的意思是您想要一段代码用于将您的条件列表与另一个列表中的参数进行逐个比较如果不匹配则打印出来)。
我建议您使用Java 8中的Streams流式处理

    static Boolean x = false;
    public static void main(String[] args) {
        
        List<List<Integer>> list1 = new ArrayList<>(Arrays.asList(Arrays.asList(1,2,3),Arrays.asList(1),Arrays.asList(1,2),Arrays.asList(2),Arrays.asList(3),Arrays.asList(3,2)));
        List<Integer> list2 = new ArrayList<>(Arrays.asList(1,2));
        
        Consumer<List<Integer>> check = list -> { if(list.equals(list2)) x = true; };
        Consumer<List<Integer>> printList =  ListPrinted -> { if(x == false){ System.out.print(ListPrinted); } };

        list1.stream().peek(check).forEach(printList);
        
    }
    
它能够工作我已经编译通过了

你可能会问为什么需要布尔变量x?!你可以将它视为停止输入的条件!!为什么我将它设为静态和全局变量?:
  因为在lambda表达式中所有的局部变量都必须是final的而我们不希望如此!),而且我们是在一个类下工作没有多个对象可以一起使用),所以我使用了static静态变量是类变量)。

我希望您能理解
英文:

if you mean that you want a code that compares each time your criteria list with the parameter from the other list (and print it if it doesn't match).
I suggest you use Streams(for Java 8)

static Boolean x = false ;
public static void main(String[] args) {
	
	List&lt;List&lt;Integer&gt;&gt; list1 = new ArrayList&lt;&gt;(Arrays.asList(Arrays.asList(1,2,3),Arrays.asList(1),Arrays.asList(1,2),Arrays.asList(2),Arrays.asList(3),Arrays.asList(3,2)));
	List&lt;Integer&gt; list2 = new ArrayList&lt;&gt;(Arrays.asList(1,2));
	 
	
	Consumer&lt;List&lt;Integer&gt;&gt; check = list-&gt;{if(list.equals(list2)) x = true ;};
	Consumer&lt;List&lt;Integer&gt;&gt; printList =  ListPrinted -&gt;{if(x==false){ System.out.print(ListPrinted); }} ;

	list1.stream().peek(check).forEach(printList);
	
	 
}

it works, I compiled it

you may ask, why the Boolean x !!? you can just consider it as a condition to stop typing !!
why I make it static and a global variable ?? :
because in lambda-expression, all local variables must be final(and we don't want that !), and we are working under one class (we don't have several objects to work with ) so I use static ( a variable is static: it is a class-variable ).

I hope you understand.

答案2

得分: 1

我认为你想要类似这样的东西。如果你的底层数组是对象,那么最简单的方式是将它们包装成列表(List)。如果它们是基本数据类型,你可能想在筛选时使用 Arrays.binarySearch,但在筛选之前你需要对流进行 Arrays.sort:

Integer[][] values = {{1, 5, 3}, {1, 3}, {5, 1}, {3, 5}};
Integer[] filter = {3, 5};

Arrays.stream(values)
      .map(x -> List.of(x))
      .filter(x -> Arrays.stream(filter)
                          .allMatch(y -> x.indexOf(y) >= 0))
      .forEach(System.out::println);

// 输出结果:
// [1, 5, 3]
// [3, 5]
英文:

I think you want something like this. It is easiest if your underlying arrays are objects, so that you can create Lists out of them. If they are primitives, you might want to use Arrays.binarySearch in the filter, but then you will have to do a Arrays.sort in your stream before the filter:

Integer[][] values = {{1,5,3},{1,3},{5,1},{3,5}};
Integer[] filter = {3,5};

Arrays.stream(values)
      .map (x -&gt; List.of(x))
      .filter( x -&gt; Arrays.stream(filter)
                          .allMatch(y -&gt; x.indexOf(y)&gt;=0))
      .forEach(System.out::println);

// output:
// [1, 5, 3]
// [3, 5]

答案3

得分: 0

可以创建List<List<Integer>>然后尝试迭代您的主列表并检查筛选列表的所有元素是否与mainList的子列表匹配

class Sample {
    public static void main(String[] args) {
        List<List<Integer>> mainList = List.of(List.of(1, 2, 3), List.of(1, 2), List.of(2));
        List<Integer> filter = List.of(1, 2);
        System.out.println("  " + mainList.stream().filter(integerList -> isListContains(filter, integerList)).collect(Collectors.toList()));
    }

    public static boolean isListContains(List<Integer> filter, List<Integer> mainList) {
        return filter.stream()
                .allMatch(
                        mainList.stream()
                                .collect(Collectors.toSet())
                                ::contains);
    }
}
您可以使用上述的Stream和筛选条件来实现相同的功能
要进行筛选您可以使用**filter.stream().allMatch(** 您可以从这里获取有关[**allMatch**][1]的更多信息

  [1]: https://beginnersbook.com/2017/11/java-8-stream-allmatch-example/
英文:

You can create List<List<Integer>> and try to iterate your main list and check if all element from filter list is matched with mainList's subList.

class Sample {
    public static void main(String[] args) {
        List&lt;List&lt;Integer&gt;&gt; mainList = List.of(List.of(1, 2, 3), List.of(1, 2), List.of(2));
        List&lt;Integer&gt; filter = List.of(1, 2);
        System.out.println(&quot;  &quot; + mainList.stream().filter(integerList -&gt; isListContains(filter, integerList)).collect(Collectors.toList()));
    }

    public static boolean isListContains(List&lt;Integer&gt; filter, List&lt;Integer&gt; mainList) {
        return filter.stream()
                .allMatch(
                        mainList.stream()
                                .collect(Collectors.toSet())
                                ::contains);
    }

}

You can implement same by using Stream and filter criteria as above.
And for filter out you can use filter.stream()allMatch( You can get more idea about allMatch from here.

答案4

得分: 0

你似乎在寻找的是:

.filter(p -> p.getAllChemVolumes().containsAll(matchingVolumes))

在这里,你需要在 ProductData 类中定义 getAllChemVolumes 方法,以便根据你所需的效率返回一个 Collection<Integer>

英文:

What you seem to be looking for is:

.filter(p -&gt; p.getAllChemVolumes().containsAll(matchingVolumes))

where you would need to define the getAllChemVolumes method within ProductData to return a Collection&lt;Integer&gt; based on the efficiency you seek.

huangapple
  • 本文由 发表于 2020年8月28日 21:13:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/63634495.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定