Using Java8 to find string values in one ArrayList present in another ArrayList using endsWith method - debugging

I have following code.
public class ComparingTwoLists {
public static void main(String[] args) {
List<String> small = Arrays.asList("AA", "BB");
List<String> big = Arrays.asList("a.b.AA", "a.b.BB", "a.b.CC");
List<String> list = new ArrayList<String>();
Consumer<String> consumer = (String outer) -> {
Stream<String> stream1 = small.stream();
Consumer<String> innerConsumer = (String inner) -> {
if (outer.endsWith(inner)) {
list.add(outer);
}
};
stream1.forEach(innerConsumer);
};
Stream<String> stream2 = big.stream();
stream2.forEach(consumer);
System.out.println(list);
}
}
I am trying to find out if string values in small is present in string values of big at end of string, using method endWith() method.
Is this efficient way of doing it?
Another problem I am facing in this code is that when I am trying to debug this code, I am able to view/inspect the value of inner, but cannot view the value of outer. Is there a way to check the value of outer while debugging.

You can do like this:
big.stream()
.filter(s -> small.stream().anyMatch(s::endsWith))
.collect(Collectors.toList());

Related

How to get all keys whose values are null in Java 8 using Map

I was going through How to remove a key from HashMap while iterating over it?, but my requirement is bit different.
class Main {
public static void main(String[] args) {
Map<String, String> hashMap = new HashMap<>();
hashMap.put("RED", "#FF0000");
hashMap.put("BLACK", null);
hashMap.put("BLUE", "#0000FF");
hashMap.put("GREEN", "#008000");
hashMap.put("WHITE", null);
// I wan't result like below - get All keys whose value is null
List<String> collect = hashMap.values()
.stream()
.filter(e -> e == null)
.collect(Collectors.toList());
System.out.println(collect);
// Result - BLACK, WHITE in list
}
}
Try this:
import java.util.*;
import java.util.stream.*;
class Main {
public static void main(String[] args) {
Map<String, String> hashMap = new HashMap<>();
hashMap.put("RED", "#FF0000");
hashMap.put("BLACK", null);
hashMap.put("BLUE", "#0000FF");
hashMap.put("GREEN", "#008000");
hashMap.put("WHITE", null);
// I wan't result like below - get All keys whose value is null
List<String> collect = hashMap.keySet()
.stream()
.filter(e -> Objects.isNull(hashMap.get(e)))
.collect(Collectors.toList());
System.out.println(collect);
// Result - BLACK, WHITE in list
}
}
As pointed out in the comments, you can try this as well:
import java.util.*;
import java.util.stream.*;
class Main {
public static void main(String[] args) {
Map<String, String> hashMap = new HashMap<>();
hashMap.put("RED", "#FF0000");
hashMap.put("BLACK", null);
hashMap.put("BLUE", "#0000FF");
hashMap.put("GREEN", "#008000");
hashMap.put("WHITE", null);
// I wan't result like below - get All keys whose value is null
List<String> collect = hashMap.entrySet()
.stream()
.filter(e -> Objects.isNull(e.getValue()))
.map(e -> e.getKey())
.collect(Collectors.toList());
System.out.println(collect);
// Result - BLACK, WHITE in list
}
}
This is more optimized, as compared to the first solution.

Java8 Streams: Remove an field from an object of the map value

I have a hash map like this
Map<String, AttributeValueUpdate> myMap = new HashMap<>;
The class AttributeValueUpdate looks like this:
public class AttributeValueUpdate {
private AttributeValue value;
private String action;
public static class Builder {
private AttributeValue value;
private String action;
public Builder() {
}
public AttributeValueUpdate.Builder withValue(AttributeValue value) {
this.value = value;
return this;
}
public AttributeValueUpdate.Builder withAction(String action) {
this.action = action;
return this;
}
protected void populate(AttributeValueUpdate instance) {
instance.setValue(this.value);
instance.setAction(this.action);
}
public AttributeValueUpdate build() {
AttributeValueUpdate instance = new AttributeValueUpdate();
this.populate(instance);
return instance;
}
}
}
The map has two entries
AttributeValueUpdate att1 = AttributeValueUpdate.builder().withAction("Add").withValue(new AttributeValue("sam").build();
AttributeValueUpdate att2 = AttributeValueUpdate.builder().withAction("Delete").withValue(new AttributeValue("john").build();
myMap.add("entry1", attr1);
myMap.add("entry2", atte2);
I want to modify mymap by deleting the "value field" from all the AttributeValueUpdate (which is value of the map), basically map's value field will be changed by removing "value field" of the AttributeValueUpdate object. How can I achieve this using java streams?
Java Stream API is not a friend with Map as long as it's collection-based (List, Set). You need to stream over the entries of the map.
As far as I understand, you want to remove (= make null) AttributeValue value of each AttributeValueUpdate instance (map's value). Here is the way to go assuming a constructor AttributeValueUpdate(String action):
Map<String, AttributeValueUpdate> updatedMap = myMap.entrySet().stream()
.map(entry -> {
String action = entry.getValue().getAction();
AttributeValueUpdate update = new AttributeValueUpdate(action);
return new SimpleEntry<>(entry.getKey(), update);
})
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
The easiest solution is using Map#replaceAll if you don't mind to mutate the map:
myMap.replaceAll((k, v) -> {
String action = v.getAction();
return new AttributeValueUpdate(action);
});

FlatFileItemWriterBuilder-headerCallback() get number of rows written

Is it possible to get the total number of rows written from FlatFileItemWriter.headerCallback()?
I am a spring-batch nubee and I looked at putting count of lines into header of flat file and Spring Batch - Counting Processed Rows.
However I can't seem to implement the logic using the advice given there. It makes sense the writer count will only be available after the file is processed. However I am trying to get the row-count just before the file is officially written.
I tried to look for a hook like #AfterStep and grab the total rows, but I keep going in circles.
#Bean
#StepScope
public FlatFileItemWriter<MyFile> generateMyFileWriter(Long jobId,Date eventDate) {
String filePath = "C:\MYFILE\COMPLETED";
Resource file = new FileSystemResource(filePath);
DelimitedLineAggregator<MyFile> myFileLineAggregator = new DelimitedLineAggregator<>();
myFileLineAggregator.setDelimiter(",");
myFileLineAggregator.setFieldExtractor(getMyFileFieldExtractor());
return new FlatFileItemWriterBuilder<MyFile>()
.name("my-file-writer")
.resource(file)
.headerCallback(new MyFileHeaderWriter(file.getFilename()))
.lineAggregator(myFileLineAggregator)
.build();
}
private FieldExtractor<MyFile> getMyFileFieldExtractor() {
final String[] fieldNames = new String[]{
"typeRecord",
"idSystem"
};
return item -> {
BeanWrapperFieldExtractor<MyFile> extractor = new BeanWrapperFieldExtractor<>();
extractor.setNames(fieldNames);
return extractor.extract(item);
};
}
Notice I am using the MyFileHeaderWriter.java class(below) in the headerCallback(new MyFileHeaderWriter(file.getFilename())) (above). I am trying to initialize the value of qtyRecordsCreated below.
class MyFileHeaderWriter implements FlatFileHeaderCallback {
private final String header;
private String dtxCreated;
private String tmxCreated;
private String fileName;//15 byte file name private String qtyRecordsCreated;//number of rows in file including the header row
MyFileHeaderWriter(String sbfFileName) {
SimpleDateFormat dateCreated = new SimpleDateFormat("YYDDD");
SimpleDateFormat timeCreated = new SimpleDateFormat("HHMM");
Date now = new Date();
this.dtxCreated = dateCreated.format(now);
this.tmxCreated = timeCreated.format(now);
this.fileName = sbfFileName; this.qtyRecordsCreated="";
String[] headerValues = {dtxCreated,tmxCreated,fileName,qtyRecordsCreated};
this.header = String.join(",", headerValues);
}
#Override
public void writeHeader(Writer writer) throws IOException {
writer.write(header);
}
}
How can I get the number of rows in the header row?
Can the FlatFileFooterCallback be used to fetch the number of rows and then update the header with number of rows in the file afterwards?
You can achieve this in ItemProcessor, try this it work for me
public class EmployeeProcessor implements ItemProcessor<Employee, Employee> {
#Override
public Employee process(Employee employee) throws Exception {
return employee;
}
#AfterStep
public void afterStep(StepExecution stepExecution) {
ExecutionContext stepContext = stepExecution.getExecutionContext();
stepContext.put("count", stepExecution.getReadCount());
System.out.println("COUNT" + stepExecution.getReadCount());
}
}
And in you writer to get value
int count = stepContext.getInt("count");
Hope work for you

Sort table on multiple Comparator items

I need a way in Java 8 to sort a list of Item objects using on multiple Comparator objects.
The application creates a Comparator on every user action. It's stores the Comparator objects in an ArrayList. It is possible to sort on one Comparator Item but now we need a way to make it possible to sort on multiple Comarator items at the same time.
This line of code I use to sort the list:
tbl.getItems().stream().sorted(groupingComparator);
The variable groupingComparator is from type Comparator<Item>
Now I need to sort on multiple fields that are stored in
ArrayList<Comparator<Item>>
Is this possible in Java 8? And how can I implement this?
You can use the thenComparing(Comparator) method available from the Comparator interface to chain multiple Comparators together. See the example below, to create such a chained Comparator from a List using streams.
The domain class we want to use for sorting:
public static class Order {
String customer;
String item;
public Order(String customer, String item)
{
this.customer = customer;
this.item = item;
}
public String toString() {
return "Customer: " + customer + " Item: " + item;
}
}
Sample code:
public static void main(String... args) throws Throwable
{
List<Order> orders = new ArrayList<>();
orders.add(new Order("A", "Item 1"));
orders.add(new Order("B", "Item 3"));
orders.add(new Order("A", "Item 2"));
orders.add(new Order("B", "Item 1"));
List<Comparator<Order>> comparators =
Arrays.asList((o1, o2) -> o1.customer.compareTo(o2.customer), // comparator for customer names
(o1, o2) -> o1.item.compareTo(o2.item)); // comparator for item names
Comparator<Order> comp =
comparators.stream()
.reduce(Comparator::thenComparing)
// use a default comparator if the comparator list was empty
.orElse(Comparator.comparing(Object::toString));
orders.stream().sorted(comp).forEach((order) -> System.out.println(order));
}
This snippet will print the Orders sorted first by Customer then by Item name.
As simple as that:
public class CompositeComparator implements Comparator<Item> {
private List<Comparator<Item>> comparators;
public CompositeComparator(List<Comparator<Item>> comparators) {
this.comparators = comparators;
}
#Override
public int compare(Item o1, Item o2) {
int result = 0;
for (Comparator<Item> c : comparators) {
result = c.compare(o1, o2);
if (result != 0) {
break;
}
}
return result;
}
}

Convert nested loops according to Java 8 nested loops

Found difficulty to change this code according to java8 lambda expression.
The code removes student object which have same name and add that object into a single entry.
public List<Student> removeDuplicates(List<Student> studentList)
{
List<Student> newStudentList=new ArrayList<Student>();
List<String> studentNames= new ArrayList<String>();
studentList.stream().forEach(e->studentNames.add(e.getName()));
List<String> studentNameList= new ArrayList<String>();
for (Student student: studentList) {
int count=0;
for (String sname: studentNames)
{
if(student.getName().equals(sname)){
count++;
}
else{
count=0;
}
if(count==1)
{ if(!studentNameList.contains(student.getName())){
studentNameList.add(student.getName());
newStudentList.add(student);
}
}
}
}
}
Try this
public Stream<Student> removeDuplicates(List<Student> studentList) {
return studentList
.stream()
.collect(
Collectors.toMap(Student::getName, s -> s,
(fst, snd) -> fst)).values().stream();
}
Here you are using java-8 streams.
public List<Student> removeDuplicates(List<Student> studentList) {
return studentList.stream()
.map(Student::getName)
.distinct()
.map(x -> studentList.stream()
.filter(y -> y.getName().equals(x))
.findFirst()
.get())
.collect(Collectors.toList());
}
I assume you must end up with a List, otherwise you would have chosen to use a Set which by definition is a unique collection. A Set could still be part of the solution, however, doing something like
Set<String> tempUniqueValues = new HashSet<>();
List<String> listWithoutDupes = myList.stream()
.filter(tempUniqueValues::add) // filters out non-unique values
.collect(Collectors.toList());

Resources