Convert list to string using Java streams - java

I created a for each loop and I get list of price code but I want to
get same things without using any loop and perform this operation
using java8 for your reference I post my old code.
I want to change only this position of my code.
List<ItemPriceCode> itemPriceCodes = item.getItemPriceCodes();
List<String> priceCodeList = new ArrayList<String>();
for (ItemPriceCode ipc : itemPriceCodes) {
//get the string value from the list
priceCodeList.add(ipc.getPriceCode());
}
But I do not want to use any loop I want to get same result without
using any loop . To over come from this issue I try this way but I am
not get any success.
itemPriceCodes.stream().map(n -> String.valueOf(n)).collect(Collectors.toList());
Here This is my full code of this function
private Item getItemManufacturerPriceCodes(Item item) {
List<ItemPriceCode> itemPriceCodes = item.getItemPriceCodes();
List<String> priceCodeList = new ArrayList<String>();
for (ItemPriceCode ipc : itemPriceCodes) {
//get the string value from the list
priceCodeList.add(ipc.getPriceCode());
}
//pass this string value in query
List<ManufacturerPriceCodes>mpc = manufacturerPriceCodesRepository.
findByManufacturerIDAndPriceCodeInAndRecordDeleted(item.getManufacturerID(),priceCodeList,NOT_DELETED);
//Convert list to map
Map<String, ManufacturerPriceCodes> ipcToMFPNameMap = mpc.stream().collect(
Collectors.toMap(ManufacturerPriceCodes :: getPriceCode,Function.identity()));// Object
for (ItemPriceCode ipcs : itemPriceCodes) {
ipcs.setManufacturerPriceCode(ipcToMFPNameMap.getClass().getName());
}
item.getItemPriceCodes()
.removeIf(ipcs -> DELETED.equals(ipcs.getRecordDeleted()));
return item;
}

It should be
List<String> priceCodeList = itemPriceCodes.stream().map(ItemPriceCode::getPriceCode)).collect(Collectors.toList());
EDIT:
Java 16+
List<String> priceCodeList = itemPriceCodes.stream().map(ItemPriceCode::getPriceCode)).toList()
Although this would return an immutable list.
Furthur reading: Differences of Java 16's Stream.toList() and Stream.collect(Collectors.toList())?
Although it doesn't seem necessary considering the use case if you want to use String.valueOf() you need to override toString accordingly in your class, as String.valueOf() uses it to get the string representation.
Definition of valueOf()
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Thus to make your code work.. add this in your class
class ItemPriceCode{
.
.
.
public String toString(){
return this.getPriceCode();
}
}

Related

How to print a nested list using java stream where the Object holds a list of references to itself

I have an object which looks similar to what's shown below:
public class Obj {
private List<Obj> objs;
private String objId;
public List<Obj> getObjs() {
return objs;
}
public String getobjId() {
return objId;
}
#Override
public String toString() {
return "Obj [objs=" + objs + ", objId=" + objId + "]";
}
}
How can I print the list of objId using streams?
EDIT
Obj can contain a list of Obj and it's children can contain a list of obj objects. If the depth is 5 levels, is it possible to print all the objId values from the top most obj to the values of the child at 5th level. I want to avoid nested for loops.
You should use recursion. One possible way to do it with streams is as follows:
private Stream<Obj> allObjs() {
return Stream.concat(
Stream.of(this),
objs == null ? Stream.empty() : objs.stream().flatMap(Obj::allObjs));
}
#Override
public String toString() {
return allObjs()
.map(Obj::getobjId)
.collect(Collectors.joining(", "));
}
Note that this works well as long as your Obj instances are arranged in a tree-like structure. If you have a specific Obj instance that is both a parent at some level and a child in some lower level (i.e. if your Obj instances form a graph), this solution won't work and you'll get a huge StackOverflowError.
If you can't modify the Obj class, you could achieve the same with helper methods that receive an instance of Obj i.e. in a ObjService class:
public static Stream<Obj> allObjs(Obj o) {
if (o == null) return Stream.empty(); // in case the argument is null
return Stream.concat(
Stream.of(o),
o.getObjs() == null ?
Stream.empty() :
o.getObjs().stream().flatMap(ObjService::allObjs));
}
public static String deepToString(Obj o) {
return ObjService.allObjs(o)
.map(Obj::getobjId)
.collect(Collectors.joining(", "));
}
Well, using Stream you can start from here:
objs.stream().
map(Obj::getObjId).
forEachOrdered(System.out::println);
And improving a little bit:
List<String> collect = objs.stream()
.filter(Objects::nonNull) // Filter only nonNull objects. Avoid NullPointerException
.map(Obj::getObjId)
.peek(System.out::println) // Print the ObjId value from Obj
.collect(Collectors.toList()); // Return the result to a List, if you need.
Now you have the basic way to get values from children. Learn a little about Stream and improve the code example ;)
Some nice links:
A Guide to Streams in Java 8
Processing Data with Java SE 8 Streams
The Java 8 Stream API Tutorial
Hope this helps!

Java - Comparing a single String value with all the String values in an ArrayList

I have an ArrayList with a set of (same) string values which I need to compare with a single String value and return true or false. Is there any way to do
that in Java?
For example, say I have a <String>ArrayList with 5 values = foo, foo, foo, foo, foo (My requirement is such that all the values in the arraylist will be the SAME) and I have a String str = "foo". I need to verify that whether ALL the values in the arraylist is the SAME as the string value i.e., all the values present in the arraylist SHOULD be "foo".
I tried to google this info and all I can see is suggestions to use contains() method, in different ways, which will return true even if anyone value in the arraylist contains the specified value.
I even figured a workaround for this - Creating another arraylist with expected values and compare the two lists using equals() method and it seems
to be working. I was just wondering whether there is any simple way to achieve this.
That's simple with Java 8:
String str = "foo";
List<String> strings = Arrays.asList("foo", "foo", "foo", "foo", "foo");
boolean allMatch = strings.stream().allMatch(s -> s.equals(str));
For Java 7 replace the last line with:
boolean allMatch = true;
for (String string : strings) {
if (!string.equals(str)) {
allMatch = false;
break;
}
}
If you want to know if the array contains the string use ArrayList::contains()
String s = "HI";
ArrayList<String> strings = // here you have your string
if (string.contains(s)) {
// do your stuff
}
If you want to check if all values are same, iterate and count. If you have JAVA8 check steffen sollution.
boolean areSame = true;
for (String str : strings) {
if (!str.equals(s)) areSame = false;
}
if (areSame) {
// all elements are same
}
1) You can the pass the arraylist into a set.
2) Now you can get the size of set, if it is equal to 1 that means all elements are same.
3) Now you can use the contains on set to check if your value is present in it or not.
public static void main(String[] args){
String toBeCompared="foo";
List<String> list=new ArrayList<String>();
list.add("foo");
list.add("foo");
list.add("foo");
list.add("foo");
list.add("foo");
Set<String> set=new HashSet<String>(list);
if(1==set.size()){
System.out.println(set.contains(toBeCompared));
}
else{
System.out.println("List has different values");
}
}
You can use this method to do that
private boolean allAreSame(ArrayList<String> stringList, String compareTo){
for(String s:stringList){
if(!s.equals(compareTo))
return false;
}
return true;
}
I would do it like this:
ArrayList<String> foos = new ArrayList<>();
String str = "foo";
for (String string : foos) {
if(string.equals(str)){
System.out.println("True");
}
}

Java, get all variable values of a class

So I have a class called Test:
public class Test{
protected String name = "boy";
protected String mainAttack = "one";
protected String secAttack = "two";
protected String mainType"three";
protected String typeSpeak = "no spoken word in super class";
//Somehow put all the class variables in an Array of some sort
String[] allStrings = ??(all class' strings);
//(and if you feel challenged, put in ArrayList without type declared.
//So I could put in, not only Strings, but also ints etc.)
public void Tester(){
//Somehow loop through array(list) and print values (for-loop?)
}
}
As you can see, I want to put all the class variables in an Array or ArrayList (or something similar) automatically.
And next I want to be able to loop through the array and print/get the values.
Preferably using an enhanced-for loop.
As other said, don't do this. But this is how:
Class<?> cl = this.getClass();
List<Object> allObjects = new ArrayList<Object>();
for (java.lang.reflect.Field f: cl.getDeclaredFields())
{
f.setAccessible(true);
try
{
Object o = f.get(this);
allObjects.add(o);
}
catch (Exception e)
{
...
}
}
for (Object o: allObjects)
System.out.println(o);
If you really really need do this you need to use Reflection.
However a much better approach would be to store the values in a Map (probably a HashMap) and then you can query/set/etc them from that easily.
You can use Map or Hashmap to store variables and its values instead of Array or Arraylist
HashMap is an object that stores both “key/value” as a pairs. In this article, we show you how to create a HashMap instance and iterates the HashMap data.
Why not use a HashMap for the values and iterate through that?
Iterate through a HashMap
Do this.
String threeEleves = "sky";
String sevenDwarves = "stone";
String nineMortal = "die";
String oneRing[] = new String[] // <<< This
{
threeElves,
sevenDwarves,
nineMortal
}
or do this
// in some class.
public void process(final String... varArgs)
{
for (String current : varArgs)
{
}
}
String one = "noodles";
String two = "get";
String three = "in";
String four = "my";
String five = "belly";
process (one, two, three, four, five);

Is it possible to avoid loop which will cast one object type to another in split() or Arrays.asList()?

I'm trying to simplify my code and I have a question: is it's possible to convert string of IDs separated by coma to specific collection type?
So, my code now is:
String [] condition_list_id_tmp = rule.getContractRuleConditions().split(",");
List<String> condition_list_id = Arrays.asList(condition_list_id_tmp);
List<Long> condition_ids = new ArrayList<Long>();
for (String str_id : condition_list_id){
condition_ids.add(Long.parseLong(str_id));
}
Can I simplify this code by using for example Type collectionType = new TypeToken<List<Long>>() {}.getType(); like in gson?
Have you considered LambdaJ?
class StringToLong implements Converter<String, Long> {
public Long convert(String str) {
return Long.parseLong(str);
}
}
String [] condition_list_id_tmp = rule.getContractRuleConditions().split(",");
List<String> condition_list_id = Arrays.asList(condition_list_id_tmp);
List<Long> condition_ids = convert(condition_list_id, new StringToLong());
or using some libraries, like guava? so that there is no looping in your codes (but in theirs) ?
I saw that your mentioned your goal is "to simplify my code"
e.g.
final List<String> strList = Arrays.asList("1,2,3,4,5".split(","));
final List<Long> l = Lists.transform(strList, new Function<String, Long>() {
#Override
public Long apply(final String input) {
return Long.parseLong(input);
}
});
I don't think so with out looping you can do this. How come your collection's content type be changed with out casting explicitly .
There is no method available without looping. Even if a method is available it will look like to you as a single operation but obviously it has to
loop internally.
For eg: Arrays.fill(arrayname, intval);
This is a single method to fill the array with any integer value. But internally it will also run a loop on the array.
java 8 can do this :
String [] condition_list_id_tmp = rule.getContractRuleConditions().split(",");
List<String> condition_list_id = Arrays.asList(condition_list_id_tmp);
List<Long> condition_ids = condition_list_id.map(c -> Long.parseLong(c))
The solution for your problem until Java 8 pop to the market could be project Guava, with their support for Functional Idioms.
Then you could perform that operation in different way, but as i wrote in the comment. At the end you will have same operation.
public static List<Long> splitToLong(String list, String token) {
StringTokenizer tokenizer= new StringTokenizer(list, token);
List<Long> result = new ArrayList<Long>();
while(tokenizer.hasMoreTokens() {
result.add(Long.parseLong(tokenizer.nextToken()));
}
}
If you put this method in some Util class, then you can enjoy clean code
//....
for(Long mLong : StringHelper.splitToLong(message,",")) {
//Do something with mLong
}
//....

How to de-dupe a List of Objects?

A Rec object has a member variable called tag which is a String.
If I have a List of Recs, how could I de-dupe the list based on the tag member variable?
I just need to make sure that the List contains only one Rec with each tag value.
Something like the following, but I'm not sure what's the best algorithm to keep track counts, etc:
private List<Rec> deDupe(List<Rec> recs) {
for(Rec rec : recs) {
// How to check whether rec.tag exists in another Rec in this List
// and delete any duplicates from the List before returning it to
// the calling method?
}
return recs;
}
Store it temporarily in a HashMap<String,Rec>.
Create a HashMap<String,Rec>. Loop through all of your Rec objects. For each one, if the tag already exists as a key in the HashMap, then compare the two and decide which one to keep. If not, then put it in.
When you're done, the HashMap.values() method will give you all of your unique Rec objects.
Try this:
private List<Rec> deDupe(List<Rec> recs) {
Set<String> tags = new HashSet<String>();
List<Rec> result = new ArrayList<Rec>();
for(Rec rec : recs) {
if(!tags.contains(rec.tags) {
result.add(rec);
tags.add(rec.tag);
}
}
return result;
}
This checks each Rec against a Set of tags. If the set contains the tag already, it is a duplicate and we skip it. Otherwise we add the Rec to our result and add the tag to the set.
This becomes easier if Rec is .equals based on its tag value. Then you could write something like:
private List<Rec> deDupe( List<Rec> recs )
{
List<Rec> retList = new ArrayList<Rec>( recs.size() );
for ( Rec rec : recs )
{
if (!retList.contains(rec))
{
retList.add(rec);
}
}
return retList;
}
I would do that with the google collections. You can use the filter function, with a predicate that remember previous tags, and filters out Rec's with tag that has been there before.
Something like this:
private Iterable<Rec> deDupe(List<Rec> recs)
{
Predicate<Rec> filterDuplicatesByTagPredicate = new FilterDuplicatesByTagPredicate();
return Iterables.filter(recs, filterDuplicatesByTagPredicate);
}
private static class FilterDuplicatesByTagPredicate implements Predicate<Rec>
{
private Set<String> existingTags = Sets.newHashSet();
#Override
public boolean apply(Rec input)
{
String tag = input.getTag();
return existingTags.add(tag);
}
}
I slightly changed the method to return Iterable instead of List, but ofcourse you change that if that's important.
If you don't care about shuffling the data around (i.e you have a small list of small objects), you can do this:
private List<T> deDupe(List<T> thisListHasDupes){
Set<T> tempSet = new HashSet<T>();
for(T t:thisListHasDupes){
tempSet.add(t);
}
List<T> deDupedList = new ArrayList<T>();
deDupedList.addAll(tempSet);
return deDupedList;
}
Remember that implmenations of Set are going to want a consistent and valid equals operator. So if you have a custom object make sure that's taken care of.

Categories