How to get Stream from an array of array of String? - java

I have following statement creating an array of array of String:
String[][] strArr = {{"Jazz","80"},{"sam","90"},{"shaam","80"},{"aditya","100"}};
Would it be possible to get stream as following? I tried it in Eclipse but got an error.
Stream<String,String> streamObj = Arrays.stream(strArr);
Tried to search on net but mostly results were showing to get stream from 1-D array of strings as shown below:
String[] stringArr = {"a","b","c","d"};
Stream<String> str = Arrays.stream(stringArr);

There is no feasible representation such as Stream<String, String> with the java.util.stream.Stream class since the generic implementation for it relies on a single type such as it declared to be:
public interface Stream<T> ...
You might still collect the mapping in your sub-arrays as a key-value pair in a Map<String, String> as:
Map<String, String> map = Arrays.stream(strArr)
.collect(Collectors.toMap(s -> s[0], s -> s[1]));
To wrap just the entries further without collecting them to a Map, you can create a Stream of SimpleEntry as :
Stream<AbstractMap.SimpleEntry<String, String>> entryStream = Arrays.stream(strArr)
.map(sub -> new AbstractMap.SimpleEntry<>(sub[0], sub[1]));

You can define a POJO called StringPair and map the stream.
public class PairStream {
public static void main(String[] args) {
String[][] strArr = {{"Jazz","80"},{"sam","90"},{"shaam","80"},{"aditya","100"}};
Arrays.stream( strArr ).map( arr -> new StringPair(arr) ).forEach( pair -> System.out.println(pair) );
}
private static class StringPair {
private final String first;
private final String second;
public StringPair(String[] array) {
this.first = array[0];
this.second = array[1];
}
#Override
public String toString() {
return "StringPair [first=" + first + ", second=" + second + "]";
}
}
}
As well as you can use Apache Commons lang Pair
public class PairStream {
public static void main(String[] args) {
String[][] strArr = {{"Jazz","80"},{"sam","90"},{"shaam","80"},{"aditya","100"}};
Arrays.stream( strArr ).map( arr -> Pair.of(arr[0],arr[1]) ).forEach( pair -> System.out.println(pair) );
}
}

Related

Convert this String into hashmap

Let's say I have an array of strings like this
String[] strings = {"game_2times",
"game_3times",
"game_4times",
"listy_bubenicek",
"listy_peneznieso"};
What I want is to create a HashMap<String, List<String>> to hold the keys and the values. The key and value of each string are separated by a "_". The resultant map for the above strings should look like the following:
"game" -> ["2times", "3times", "4times"]
"listy" -> ["bubenicek", "peneznieso"]
I tried this
for (String item: names) {
for (int i = 0; i < names.length; i++) {
ArrayList<String> c = new ArrayList<>();
if(names[i].contains("game")) {
c.add(item);
}
hashmap.put(item.split("_")[0],c);
}
}
Here is one way using streams.
String[] strings = {
"game_2times","game_3times","game_4times","listy_bubenicek",
"listy_peneznieso"
};
stream the string array using Arrays.stream
Use String.split to split each string on the _ to create an array of s[] of the two elements
use Collectors.groupingBy to group based on a key, in this case, s[0]
then use Collectors.mapping to map to s[1] and put in a list.
Map<String, List<String>> result = Arrays.stream(strings)
.map(str -> str.split("_"))
.collect(Collectors.groupingBy(s -> s[0],
Collectors.mapping(s -> s[1], Collectors.toList())));
result.entrySet().forEach(System.out::println);
prints
game=[2times, 3times, 4times]
listy=[bubenicek, peneznieso]
Here is another option sans streams.
create a map to hold the results
Iterate thru the array, splitting the string as before.
computeIfAbsent will use the supplied argument as a key if it isn't present and will create and return the value of the function, in this case, an ArrayList.
then this and subsequent references to that key will add the value to the list for that key.
Map<String, List<String>> result = new HashMap<>();
for(String str : strings) {
String[] strArray = str.split("_");
result.computeIfAbsent(strArray[0], v->new ArrayList<>()).add(strArray[1]);
}
There are more elegant ways of doing this but I will show the simple to understand way:
public static Map<String, List<String>> flatten(List<String> names) {
final Map<String, List<String>> result = new HashMap<>();
for (String item : names) {
final String[] parts = item.split("_");
if (result.containsKey(parts[0])) {
result.get(parts[0]).add(parts[1]);
} else {
final ArrayList<String> c = new ArrayList<>();
c.add(parts[1]);
result.put(parts[0], c);
}
}
return result;
}

Iterate a list of query results in Java and create objects based on a key value

I performed a query and get a result list of this object:
public MyObject {
private String key;
private String value1;
private Integer value2;
}
The results looks like this:
key     value1       value2
1         WWW       EEE
1         WWW       AAA
2       WWW        EEE
I would like to iterate this list and create a list of something like this, grouping it by key.
//first object of the list
public MyCreatedObject {
private String key; //1
private List<Value1> value1List; //WWW, WWW
private List<Value2> value2List; //EEE, AAA
}
//second object of the list
public MyCreatedObject {
private String key; //2
private List<Value1> value1List; //WWW
private List<Value2> value2List; //EEE
}
I'm tried using stream, iterating and a couple of things but I'm really struggling with this.
Can someone give me some help?
Thanks a lot folks
You can use MyCreatedObject as a collector by adding a couple of methods:
static Collector<MyObject, ?, MyCreatedObject> collector() {
return Collector.of(MyCreatedObject::new, MyCreatedObject::add, MyCreatedObject::merge);
}
void add(MyObject o) {
key = o.key;
value1List.add(o.value1);
value2List.add(o.value2);
}
MyCreatedObject merge(MyCreatedObject other) {
key = other.key;
value1List.addAll(other.value1List);
value2List.addAll(other.value2List);
return this;
}
Then use it as a downstream collector for groupingBy():
Map<String, MyCreatedObject> grouped = list.stream()
.collect(Collectors.groupingBy(o -> o.key, MyCreatedObject.collector()));
Ideone Demo
Alternatively, you can convert add() to a constructor and group using toMap():
Map<String, MyCreatedObject> grouped = list.stream()
.collect(Collectors.toMap(o -> o.key, MyCreatedObject::new, MyCreatedObject::merge));
Ideone Demo 2
Try this.
record MyObject(String key, String value1, String value2) {}
record MyCreatedObject(String key, List<String> value1List, List<String> value2List) {}
public static void main(String[] args) {
List<MyObject> list = List.of(
new MyObject("1", "WWW", "EEE"),
new MyObject("1", "WWW", "AAA"),
new MyObject("2", "WWW", "EEE"));
Map<String, MyCreatedObject> map = new LinkedHashMap<>();
for (MyObject obj : list) {
MyCreatedObject c = map.computeIfAbsent(obj.key(),
k -> new MyCreatedObject(k, new ArrayList<>(), new ArrayList<>()));
c.value1List().add(obj.value1());
c.value2List().add(obj.value2());
}
List<MyCreatedObject> result = new ArrayList<>(map.values());
for (MyCreatedObject obj : result)
System.out.println(obj);
}
output:
MyCreatedObject[key=1, value1List=[WWW, WWW], value2List=[EEE, AAA]]
MyCreatedObject[key=2, value1List=[WWW], value2List=[EEE]]
Collectors.toMap with the merge function may be used to build a map Map<String, MyCreatedObject> and then convert its values to the list, providing that appropriate all-args constructor of MyCreatedObject is provided:
List<MyObject> input = ... ; // setup input data
List<MyCreatedObject> result = new ArrayList<>(input
.stream()
.collect(Collectors.toMap(
MyObject::getKey, //
mo -> new MyCreatedObject(
mo.getKey(),
new ArrayList<>(Arrays.asList(mo.getValue1())),
new ArrayList<>(Arrays.asList(mo.getValue2()))
),
(co1, co2) -> { // merge inner lists in MyCreatedObject
co1.getValue1List().addAll(co2.getValue1List());
co1.getValue2List().addAll(co2.getValue2List());
return co1;
}
//, LinkedHashMap::new // optional supplier to keep insertion order
))
.values()
);

converting java 7 nested for loops to use java 8 streams API

I have an example here which basically returns list based on simple logic
Given an input list and a list of grouping objects, which has a list field, the method should return a list that contains either all the members of grouping.list if the grouping.name matches any of the strings in the input list OR simply add the input string to the returning list.
After I writing this code, I am thinking it could be made simpler in Java 7 and a better example to use Java 8 Streaming API.
public class CollectorExample {
public static void main(String[] args){
List<String> input = new ArrayList<>();
input.add("foo");
input.add("bar");
input.add("foobar");
input.add("java");
List<String> list1 = new ArrayList<>();
list1.add("hello");
list1.add("world");
List<String> list2 = new ArrayList<>();
list2.add("spring");
list2.add("multi-threaded");
Grouping g1 = new Grouping("foobar",list1);
Grouping g2 = new Grouping("java",list2);
List<Grouping> groupingList = new ArrayList<>();
groupingList.add(g1);
groupingList.add(g2);
System.out.println(mapAndMerge(input,groupingList));
}
public static List<String> mapAndMerge(List<String> input, List<Grouping> groupingList){
Set<String> returnDocs = new HashSet<>();
Iterator<String> it = input.iterator();
while(it.hasNext()){
String doc = it.next();
boolean found = false;
for (Grouping lg : groupingList){
if (lg.getName().equals(doc)){
returnDocs.addAll(lg.getList());
found=true;
}
}
if (!found){
returnDocs.add(doc);
}
}
return new ArrayList<>(returnDocs);
}
}
class Grouping {
List<String> list;
String name;
public Grouping(String name, List<String> list){
this.list=list;
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
}
This outputs [spring, bar, world, foo, hello, multi-threaded] which is correct.
Here is my Java 8 syntax that I tried and did NOT work;
// List<String> mergedDocs =
// input.forEach(doc->
// groupingList.stream().map( g -> g.getName().equals(doc) ? e.getList() : doc ).collect(Collectors.toList()));
// return mergedDocs;
You can make this a lot simpler by not using your Grouping class but using a simple Map<String, List<String>> instead. This map would act as the grouping, holding the list for a given name. This also enables to have a much better performance since looking into the map is constant-time (whereas your solution is in linear time since it traverses the grouping to find a matching one).
If you have to use the List<Grouping>, you can still pre-process it to convert into an intermediate Map:
The mapAndMerge method simply becomes:
public static List<String> mapAndMerge(List<String> input, List<Grouping> groupingList) {
Map<String, List<String>> map = groupingList.stream().collect(Collectors.toMap(Grouping::getName, Grouping::getList));
return input.stream()
.flatMap(s -> map.getOrDefault(s, Arrays.asList(s)).stream())
.collect(Collectors.toList());
}
Each input is flat mapped to the list contained in the map or a default list containing the current element. Then this is collected to a new list. This code prints:
[foo, bar, hello, world, spring, multi-threaded]
You can re-write the mapAndMerge method following way using java 8. But it is not very concise as you like.
public static List<String> mapAndMerge(List<String> input,
List<Grouping> groupingList) {
Set<String> returnDocs = input
.stream()
.map(t -> groupingList
.stream()
.filter(g -> g.getName().equals(t))
.map(v -> v.getList())
.findAny()
.orElse(Arrays.asList(t)))
.flatMap(t -> t.stream())
.collect(Collectors.toSet());
return new ArrayList<>(returnDocs);
}
I think it would be much simple and clearer if you use Map instead of the Grouping class.
So that's what you'll have in the main() method:
Map<String, List<String>> groupingMap = new HashMap<>();
groupingMap.put("foobar", list1);
groupingMap.put("java", list2);
List<String> mergedDocs = new ArrayList<>();
input.stream()
.map(doc -> groupingMap.getOrDefault(doc, Collections.singletonList(doc)))
.forEach(mergedDocs::addAll);
System.out.println(mergedDocs);

How to expand and do regroup a List of List using Java 8 Stream?

I have a list of the Class A, that includes a List itself.
public class A {
public double val;
public String id;
public List<String> names = new ArrayList<String>();
public A(double v, String ID, String name)
{
val = v;
id = ID;
names.add(name);
}
static public List<A> createAnExample()
{
List<A> items = new ArrayList<A>();
items.add(new A(8.0,"x1","y11"));
items.add(new A(12.0, "x2", "y21"));
items.add(new A(24.0,"x3","y31"));
items.get(0).names.add("y12");
items.get(1).names.add("y11");
items.get(1).names.add("y31");
items.get(2).names.add("y11");
items.get(2).names.add("y32");
items.get(2).names.add("y33");
return items;
}
The aim is to sum over average val per id over the List. I added the code in Main function by using some Java 8 stream.
My question is how can I rewrite it in a more elegant way without using the second Array and the for loop.
static public void main(String[] args) {
List<A> items = createAnExample();
List<A> items2 = new ArrayList<A>();
for (int i = 0; i < items.size(); i++) {
List<String> names = items.get(i).names;
double v = items.get(i).val / names.size();
String itemid = items.get(i).id;
for (String n : names) {
A item = new A(v, itemid, n);
items2.add(item);
}
}
Map<String, Double> x = items2.stream().collect(Collectors.groupingBy(item ->
item.names.isEmpty() ? "NULL" : item.names.get(0), Collectors.summingDouble(item -> item.val)));
for (Map.Entry entry : x.entrySet())
System.out.println(entry.getKey() + " --> " + entry.getValue());
}
You can do it with flatMap:
x = items.stream()
.flatMap(a -> a.names.stream()
.map(n -> new AbstractMap.SimpleEntry<>(n, a.val / a.names.size()))
).collect(groupingBy(
Map.Entry::getKey, summingDouble(Map.Entry::getValue)
));
If you find yourself dealing with problems like these often, consider a static method to create a Map.Entry:
static<K,V> Map.Entry<K,V> entry(K k, V v) {
return new AbstractMap.SimpleImmutableEntry<>(k,v);
}
Then you would have a less verbose .map(n -> entry(n, a.val/a.names.size()))
In my free StreamEx library which extends standard Stream API there are special operations which help building such complex maps. Using the StreamEx your problem can be solved like this:
Map<String, Double> x = StreamEx.of(createAnExample())
.mapToEntry(item -> item.names, item -> item.val / item.names.size())
.flatMapKeys(List::stream)
.grouping(Collectors.summingDouble(v -> v));
Here mapToEntry creates stream of map entries (so-called EntryStream) where keys are lists of names and values are averaged vals. Next we use flatMapKeys to flatten the keys leaving values as is (so we have stream of Entry<String, Double>). Finally we group them together summing the values for repeating keys.

How to count the number of occurrences of an element in a List

I have an ArrayList, a Collection class of Java, as follows:
ArrayList<String> animals = new ArrayList<String>();
animals.add("bat");
animals.add("owl");
animals.add("bat");
animals.add("bat");
As you can see, the animals ArrayList consists of 3 bat elements and one owl element. I was wondering if there is any API in the Collection framework that returns the number of bat occurrences or if there is another way to determine the number of occurrences.
I found that Google's Collection Multiset does have an API that returns the total number of occurrences of an element. But that is compatible only with JDK 1.5. Our product is currently in JDK 1.6, so I cannot use it.
I'm pretty sure the static frequency-method in Collections would come in handy here:
int occurrences = Collections.frequency(animals, "bat");
That's how I'd do it anyway. I'm pretty sure this is jdk 1.6 straight up.
In Java 8:
Map<String, Long> counts =
list.stream().collect(Collectors.groupingBy(e -> e, Collectors.counting()));
Alternative Java 8 solution using Streams:
long count = animals.stream().filter(animal -> "bat".equals(animal)).count();
This shows, why it is important to "Refer to objects by their interfaces" as described in Effective Java book.
If you code to the implementation and use ArrayList in let's say, 50 places in your code, when you find a good "List" implementation that count the items, you will have to change all those 50 places, and probably you'll have to break your code ( if it is only used by you there is not a big deal, but if it is used by someone else uses, you'll break their code too)
By programming to the interface you can let those 50 places unchanged and replace the implementation from ArrayList to "CountItemsList" (for instance ) or some other class.
Below is a very basic sample on how this could be written. This is only a sample, a production ready List would be much more complicated.
import java.util.*;
public class CountItemsList<E> extends ArrayList<E> {
// This is private. It is not visible from outside.
private Map<E,Integer> count = new HashMap<E,Integer>();
// There are several entry points to this class
// this is just to show one of them.
public boolean add( E element ) {
if( !count.containsKey( element ) ){
count.put( element, 1 );
} else {
count.put( element, count.get( element ) + 1 );
}
return super.add( element );
}
// This method belongs to CountItemList interface ( or class )
// to used you have to cast.
public int getCount( E element ) {
if( ! count.containsKey( element ) ) {
return 0;
}
return count.get( element );
}
public static void main( String [] args ) {
List<String> animals = new CountItemsList<String>();
animals.add("bat");
animals.add("owl");
animals.add("bat");
animals.add("bat");
System.out.println( (( CountItemsList<String> )animals).getCount( "bat" ));
}
}
OO principles applied here: inheritance, polymorphism, abstraction, encapsulation.
Sorry there's no simple method call that can do it. All you'd need to do though is create a map and count frequency with it.
HashMap<String,int> frequencymap = new HashMap<String,int>();
foreach(String a in animals) {
if(frequencymap.containsKey(a)) {
frequencymap.put(a, frequencymap.get(a)+1);
}
else{ frequencymap.put(a, 1); }
}
There is no native method in Java to do that for you. However, you can use IterableUtils#countMatches() from Apache Commons-Collections to do it for you.
Simple Way to find the occurrence of string value in an array using Java 8 features.
public void checkDuplicateOccurance() {
List<String> duplicateList = new ArrayList<String>();
duplicateList.add("Cat");
duplicateList.add("Dog");
duplicateList.add("Cat");
duplicateList.add("cow");
duplicateList.add("Cow");
duplicateList.add("Goat");
Map<String, Long> couterMap = duplicateList.stream().collect(Collectors.groupingBy(e -> e.toString(),Collectors.counting()));
System.out.println(couterMap);
}
Output : {Cat=2, Goat=1, Cow=1, cow=1, Dog=1}
You can notice "Cow" and cow are not considered as same string, in case you required it under same count, use .toLowerCase(). Please find the snippet below for the same.
Map<String, Long> couterMap = duplicateList.stream().collect(Collectors.groupingBy(e -> e.toString().toLowerCase(),Collectors.counting()));
Output : {cat=2, cow=2, goat=1, dog=1}
To achieve that one can do it in several ways, namely:
Methods that return the number of occurrence of a single element:
Collection Frequency
Collections.frequency(animals, "bat");
Java Stream:
Filter
animals.stream().filter("bat"::equals).count();
Just iteration thought the list
public static long manually(Collection<?> c, Object o){
int count = 0;
for(Object e : c)
if(e.equals(o))
count++;
return count;
}
Methods that create a map of frequencies:
Collectors.groupingBy
Map<String, Long> counts =
animals.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
merge
Map<String, Long> map = new HashMap<>();
c.forEach(e -> map.merge(e, 1L, Long::sum));
Manually
Map<String, Integer> mp = new HashMap<>();
animals.forEach(animal -> mp.compute(animal, (k, v) -> (v == null) ? 1 : v + 1));
A running example with all the methods:
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public class Frequency {
public static int frequency(Collection<?> c, Object o){
return Collections.frequency(c, o);
}
public static long filter(Collection<?> c, Object o){
return c.stream().filter(o::equals).count();
}
public static long manually(Collection<?> c, Object o){
int count = 0;
for(Object e : c)
if(e.equals(o))
count++;
return count;
}
public static Map<?, Long> mapGroupBy(Collection<?> c){
return c.stream()
.collect(Collectors.groupingBy(Function.identity() , Collectors.counting()));
}
public static Map<Object, Long> mapMerge(Collection<?> c){
Map<Object, Long> map = new HashMap<>();
c.forEach(e -> map.merge(e, 1L, Long::sum));
return map;
}
public static Map<Object, Long> manualMap(Collection<?> c){
Map<Object, Long> map = new HashMap<>();
c.forEach(e -> map.compute(e, (k, v) -> (v == null) ? 1 : v + 1));
return map;
}
public static void main(String[] args){
List<String> animals = new ArrayList<>();
animals.add("bat");
animals.add("owl");
animals.add("bat");
animals.add("bat");
System.out.println(frequency(animals, "bat"));
System.out.println(filter(animals,"bat"));
System.out.println(manually(animals,"bat"));
mapGroupBy(animals).forEach((k, v) -> System.out.println(k + " -> "+v));
mapMerge(animals).forEach((k, v) -> System.out.println(k + " -> "+v));
manualMap(animals).forEach((k, v) -> System.out.println(k + " -> "+v));
}
}
The methods name should have reflected what those methods are doing, however, I used the name to reflect the approach being used instead (given that in the current context it is okey).
I wonder, why you can't use that Google's Collection API with JDK 1.6. Does it say so? I think you can, there should not be any compatibility issues, as it is built for a lower version. The case would have been different if that were built for 1.6 and you are running 1.5.
Am I wrong somewhere?
Actually, Collections class has a static method called : frequency(Collection c, Object o) which returns the number of occurrences of the element you are searching for, by the way, this will work perfectly for you:
ArrayList<String> animals = new ArrayList<String>();
animals.add("bat");
animals.add("owl");
animals.add("bat");
animals.add("bat");
System.out.println("Freq of bat: "+Collections.frequency(animals, "bat"));
A slightly more efficient approach might be
Map<String, AtomicInteger> instances = new HashMap<String, AtomicInteger>();
void add(String name) {
AtomicInteger value = instances.get(name);
if (value == null)
instances.put(name, new AtomicInteger(1));
else
value.incrementAndGet();
}
To get the occurrences of the object from the list directly:
int noOfOccurs = Collections.frequency(animals, "bat");
To get the occurrence of the Object collection inside list, override the equals method in the Object class as:
#Override
public boolean equals(Object o){
Animals e;
if(!(o instanceof Animals)){
return false;
}else{
e=(Animals)o;
if(this.type==e.type()){
return true;
}
}
return false;
}
Animals(int type){
this.type = type;
}
Call the Collections.frequency as:
int noOfOccurs = Collections.frequency(animals, new Animals(1));
What you want is a Bag - which is like a set but also counts the number of occurances. Unfortunately the java Collections framework - great as they are dont have a Bag impl. For that one must use the Apache Common Collection link text
List<String> list = Arrays.asList("as", "asda", "asd", "urff", "dfkjds", "hfad", "asd", "qadasd", "as", "asda",
"asd", "urff", "dfkjds", "hfad", "asd", "qadasd" + "as", "asda", "asd", "urff", "dfkjds", "hfad", "asd",
"qadasd", "as", "asda", "asd", "urff", "dfkjds", "hfad", "asd", "qadasd");
Method 1:
Set<String> set = new LinkedHashSet<>();
set.addAll(list);
for (String s : set) {
System.out.println(s + " : " + Collections.frequency(list, s));
}
Method 2:
int count = 1;
Map<String, Integer> map = new HashMap<>();
Set<String> set1 = new LinkedHashSet<>();
for (String s : list) {
if (!set1.add(s)) {
count = map.get(s) + 1;
}
map.put(s, count);
count = 1;
}
System.out.println(map);
​If you use Eclipse Collections, you can use a Bag. A MutableBag can be returned from any implementation of RichIterable by calling toBag().
MutableList<String> animals = Lists.mutable.with("bat", "owl", "bat", "bat");
MutableBag<String> bag = animals.toBag();
Assert.assertEquals(3, bag.occurrencesOf("bat"));
Assert.assertEquals(1, bag.occurrencesOf("owl"));
The HashBag implementation in Eclipse Collections is backed by a MutableObjectIntMap.
Note: I am a committer for Eclipse Collections.
Put the elements of the arraylist in the hashMap to count the frequency.
So do it the old fashioned way and roll your own:
Map<String, Integer> instances = new HashMap<String, Integer>();
void add(String name) {
Integer value = instances.get(name);
if (value == null) {
value = new Integer(0);
instances.put(name, value);
}
instances.put(name, value++);
}
Java 8 - another method
String searched = "bat";
long n = IntStream.range(0, animals.size())
.filter(i -> searched.equals(animals.get(i)))
.count();
package traversal;
import java.util.ArrayList;
import java.util.List;
public class Occurrance {
static int count;
public static void main(String[] args) {
List<String> ls = new ArrayList<String>();
ls.add("aa");
ls.add("aa");
ls.add("bb");
ls.add("cc");
ls.add("dd");
ls.add("ee");
ls.add("ee");
ls.add("aa");
ls.add("aa");
for (int i = 0; i < ls.size(); i++) {
if (ls.get(i) == "aa") {
count = count + 1;
}
}
System.out.println(count);
}
}
Output: 4
Integer[] spam = new Integer[] {1,2,2,3,4};
List<Integer> list=Arrays.asList(spam);
System.out.println(list.stream().collect(Collectors.groupingBy(Function.identity(),Collectors.counting())));
System.out.println(list.stream().collect(Collectors.groupingBy(Function.identity(),HashMap::new,Collectors.counting())));
output
{1=1, 2=2, 3=1, 4=1}
If you are a user of my ForEach DSL, it can be done with a Count query.
Count<String> query = Count.from(list);
for (Count<Foo> each: query) each.yield = "bat".equals(each.element);
int number = query.result();
I didn't want to make this case more difficult and made it with two iterators
I have a HashMap with LastName -> FirstName. And my method should delete items with dulicate FirstName.
public static void removeTheFirstNameDuplicates(HashMap<String, String> map)
{
Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();
Iterator<Map.Entry<String, String>> iter2 = map.entrySet().iterator();
while(iter.hasNext())
{
Map.Entry<String, String> pair = iter.next();
String name = pair.getValue();
int i = 0;
while(iter2.hasNext())
{
Map.Entry<String, String> nextPair = iter2.next();
if (nextPair.getValue().equals(name))
i++;
}
if (i > 1)
iter.remove();
}
}
List<String> lst = new ArrayList<String>();
lst.add("Ram");
lst.add("Ram");
lst.add("Shiv");
lst.add("Boss");
Map<String, Integer> mp = new HashMap<String, Integer>();
for (String string : lst) {
if(mp.keySet().contains(string))
{
mp.put(string, mp.get(string)+1);
}else
{
mp.put(string, 1);
}
}
System.out.println("=mp="+mp);
Output:
=mp= {Ram=2, Boss=1, Shiv=1}
Map<String,Integer> hm = new HashMap<String, Integer>();
for(String i : animals) {
Integer j = hm.get(i);
hm.put(i,(j==null ? 1 : j+1));
}
for(Map.Entry<String, Integer> val : hm.entrySet()) {
System.out.println(val.getKey()+" occurs : "+val.getValue()+" times");
}
You can use groupingBy feature of Java 8 for your use case.
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class Test {
public static void main(String[] args) {
List<String> animals = new ArrayList<>();
animals.add("bat");
animals.add("owl");
animals.add("bat");
animals.add("bat");
Map<String,Long> occurrenceMap =
animals.stream().collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));
System.out.println("occurrenceMap:: " + occurrenceMap);
}
}
Output
occurrenceMap:: {bat=3, owl=1}

Categories