Processing a list of rx.Observables - java

I want to process a List<Observable<MyResponse>>. How can I do this?Had a look at Observable.zip() but unable to arrive at a conclusion.
Code snippet of what I wanna do:
List<String> myList = myMethod(); // myMethod() returns a List<String> of any possible length.
List<Observable<MyResponse>> observables = new ArrayList<>();
for (String value : myList) {
observableList.add(myAPI.getData(value))
}
// How to? : For each Observable<MyResponse> in observables call a method myProcessor(MyResponse, ...)

You can flatMap the myList:
Flowable.fromIterable(myList)
.flatMap(value -> myAPI.getData(value))
.doOnNext(myResponse -> { /* ... */ })
...

I tried again & the following worked for me:
List<Observable<MyResponse>> observables = new ArrayList<>();
List<String> values = getValues();
for (String value : values) {
observables.add(myAPI.myMethod());
}
Observable.zip(observables, new FuncN() {
#Override
public Object call(Object... args) {
for (Object arg : args) {
process((MyResponse(arg));
}
return null;
}
}).toBlocking().first();

Related

Grouping and sorting Lists into a Map

Before anything, the title doesn't convey what I really want to ask.
What I want to know is, how can I make a map, where for several users, it collects their Data and then groups it all together. I'm currently using two lists, one for the users' names and another for their works. I tried using a map.put but it kept overwriting the previous entry. So what I'd like to obtain is as follows;
Desired output:
{user1 = work1, work2, work3 , user2 = work1, work2 , userN = workN}
Current output:
{[user1, user2, user3, user4]=[work1, work2, work3, work4, work5 (user1) , work1 (user2), work1, work2, work3 ( user3 )]}
This is the code that I'm currently using to achieve the above.
private static Map<List<String>, List<String>> repositoriesUserData = new HashMap<>();
private static Set<String> collaboratorNames = new HashSet<>();
public static void main(String[] args) throws Exception {
login();
getCollabs(GITHUB_REPO_NAME);
repositoriesUnderUser();
}
public GitManager(String AUTH, String USERNAME, String REPO_NAME) throws IOException {
this.GITHUB_LOGIN = USERNAME;
this.GITHUB_OAUTH = AUTH;
this.GITHUB_REPO_NAME = REPO_NAME;
this.githubLogin = new GitHubBuilder().withOAuthToken(this.GITHUB_OAUTH, this.GITHUB_LOGIN).build();
this.userOfLogin = this.githubLogin.getUser(GITHUB_LOGIN);
}
public static void login() throws IOException {
new GitManager(GIT_TOKEN, GIT_LOGIN, GITHUB_REPO_NAME);
connect();
}
public static void connect() throws IOException {
if (githubLogin.isCredentialValid()) {
valid = true;
githubLogin.connect(GITHUB_LOGIN, GITHUB_OAUTH);
userOfLogin = githubLogin.getUser(GITHUB_LOGIN);
}
}
public static String getCollabs(String repositoryName) throws IOException {
GHRepository collaboratorsRepository = userOfLogin.getRepository(repositoryName);
collaboratorNames = collaboratorsRepository.getCollaboratorNames();
String collaborators = collaboratorNames.toString();
System.out.println("Collaborators for the following Repository: " + repositoryName + "\nAre: " + collaborators);
String out = "Collaborators for the following Repository: " + repositoryName + "\nAre: " + collaborators;
return out;
}
public static List<String> fillList() {
List<String> collaborators = new ArrayList<>();
collaboratorNames.forEach(s -> {
collaborators.add(s);
});
return collaborators;
}
public static String repositoriesUnderUser() throws IOException {
GHUser user;
List<String> names = new ArrayList<>();
List<String> repoNames = new ArrayList<>();
for (int i = 0; i < fillList().size(); i++) {
user = githubLogin.getUser(fillList().get(i));
Map<String, GHRepository> temp = user.getRepositories();
names.add(user.getLogin());
temp.forEach((c, b) -> {
repoNames.add(b.getName());
});
}
repositoriesUserData.put(names,repoNames);
System.out.println(repositoriesUserData);
return "temporaryReturn";
}
All help is appreciated!
I'll give it a try (code in question still not working for me):
If I understood correctly, you want a Map, that contains the repositories for each user.
So therefore i think the repositoriesUserData should be a Map<String, List<String>.
With that in mind, lets fill the map in each loop-cycle with the user from the lists as key and the list of repository-names as value.
The method would look like this (removed the temporary return and replaced it with void)
public static String repositoriesUnderUser() throws IOException {
for (int i = 0; i < fillList().size(); i++) {
GHUser user = githubLogin.getUser(fillList().get(i));
Map<String, GHRepository> temp = user.getRepositories();
repositoriesUserData.put(user.getLogin(), temp.values().stream().map(GHRepository::getName).collect(Collectors.toList()));
}
return "temporaryReturn";
}
Edit: (Short explanation what is happening in your code)
You are collecting all usernames to the local List names and also adding all repository-names to the local List 'repoNames'.
At the end of the method you put a new entry to your map repositoriesUserData.
That means at the end of the method you just added one single entry to the map where
key = all of the users
value = all of the repositories from the users (because its a list, if two users have the same repository, they are added twice to this list)

RxJava PublishSubject subscribe doesn't give anything. Something's wtong with subscription?

Learning RxJava so will be appreciate for any advice.
Need to receive objects when calculation is ready, so I made PublishSubject in models method:
public PublishSubject<BaseUnit> exec(int inputNumber) {
if (unitList.size() > 0) {
for (BaseUnit unit : unitList) {
unit.setInProgress();
}
}
PublishSubject<BaseUnit> subject = PublishSubject.create();
list = new ArrayList<>();
populateList(inputNumber).
subscribeOn(Schedulers.from(Executors.newFixedThreadPool(ThreadPool.getPoolSize())))
.subscribe(calculatedList -> {
list = calculatedList;
for (List<Integer> elem : list) {
for (ListOperationName operationName : ListOperationName.values()) {
ListUnit unit = new ListUnit(operationName, elem, 0);
calculate(unit);
unitList.add(unit);
subject.onNext(unit);
}
}
}, error -> Log.d("ERROR", error.toString()));
return subject;
}
public Observable<ArrayList<List<Integer>>> populateList(int inputNumber) {
return Observable.fromCallable(() -> {
ArrayList<List<Integer>> list = new ArrayList<>();
Integer[] populatedArray = new Integer[inputNumber];
Arrays.fill(populatedArray, insertValue);
list.add(new ArrayList<>(Arrays.asList(populatedArray)));
list.add(new LinkedList<>(Arrays.asList(populatedArray)));
list.add(new CopyOnWriteArrayList<>(Arrays.asList(populatedArray)));
return list;
});
}
And then trying to subscribe in presenter:
public void calculate(int inputNumber) {
fragment.showAllProgressBars();
repository.exec(inputNumber)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.from(Executors.newFixedThreadPool(ThreadPool.getPoolSize())))
.subscribe(unit -> {
Log.d("PRESENTER RESULT", unit.toString());
fragment.setCellText(unit.getViewId(), unit.getTimeString());
}, error -> Log.d("PRESENTER ERROR", error.toString()));
}
This gives me nothing. But if I use ReplaySubject - it gives me all results, but seems like it uses only one thread. So I assume there is somethings wrong I made with subscription and it should be somewhere earlier.
I need to use exactly PublishSubject for giving me results as they are ready using multiple threads.
How to fix that? Or maybe there is other problem?

Java : Jline3 : Autocomplete with more than one word

I would like to auto complete using more than one word, for example:
> we can<TAB>
welcome_trashcan pecan_seaweed yeswecan canwest
So all the suggestions should contain both of the keywords. Ideally, it should work for unlimited keywords.
I read the completion wiki, but I don't know which path to follow to achieve this.
I ended up implementing a new Interface (its written in groovy):
class MatchAnyCompleter implements Completer {
protected final List<Candidate> candidateList = []
MatchAnyCompleter(List<String> list) {
assert list
list.each {
candidateList << new Candidate(AttributedString.stripAnsi(it), it, null, null, null, null, true)
}
}
#Override
void complete(final LineReader reader, final ParsedLine commandLine, final List<Candidate> selected) {
assert commandLine != null
assert selected != null
selected.addAll(candidateList.findAll {
Candidate candidate ->
commandLine.words().stream().allMatch {
String keyword ->
candidate.value().contains(keyword)
}
})
}
}
Test:
class MatchAnyCompleterTest extends Specification {
def "Testing matches"() {
setup:
def mac = new MatchAnyCompleter([
"somevalue",
"welcome_trashcan",
"pecan_seaweed",
"yeswecan",
"canwest",
"nomatchhere"
])
def cmdLine = new ParsedLine() {
// non-implemented methods were removed for simplicity
#Override
List<String> words() {
return ["we","can"]
}
}
List<Candidate> selected = []
mac.complete(null, cmdLine, selected)
expect:
selected.each {
println it.value()
}
assert selected.size() == 4
}
}
output:
welcome_trashcan
pecan_seaweed
yeswecan
canwest

How can I call an arraylist that I already have loaded with my database inside the XML

I'm using ZK and I have this code that works me statically
<zscript>
<![CDATA[
List tipo_servicios = new ArrayList();
List tipo_servicios_enc = new ArrayList();
DTO.Tiposervicio tipo_servicios_select;
DTO.Tiposervicio tiposervicio = new DTO.Tiposervicio();
tiposervicio.setId(1);
tiposervicio.setName("Mustang");
tiposervicio.setDescripcion("New Mustang 2018");
tiposervicio.setEstatus('A');
tipo_servicios.add(tiposervicio);
void buscarTipoServicios()
{
if (keywordBox.getValue() != null && !keywordBox.getValue().trim().equals(""))
{
tipo_servicios_enc.clear();
for (DTO.Tiposervicio tipo_serv : tipo_servicios)
{
if (tipo_serv.getName().toLowerCase().contains(keywordBox.getValue().trim().toLowerCase()) || tipo_serv.getName().toLowerCase().contains(keywordBox.getValue().trim().toLowerCase()))
{
tipo_servicios_enc.add(tipo_serv);
}
}
binder.loadAll();
}
}
]]>
</zscript>
It's a search engine
void buscarTipoServicios()
And I have in my service package my next code that is used to load my array from the database
public class ConsultarTipoServicio extends SelectorComposer
{
private List<Tiposervicio> listaTipoServicio;
private TiposervicioJpaController tipoServicioJpaController;
public ConsultarTipoServicio() throws Exception
{
EntityManagerFactory emf =Persistence.createEntityManagerFactory("ProyectoLabIIPU");
tipoServicioJpaController=new TiposervicioJpaController(emf);
listaTipoServicio= tipoServicioJpaController.findTiposervicioEntities();
}
public List<Tiposervicio> getlistaTipoServicio()
{
return listaTipoServicio;
}
}
I want somehow to assign to my
List tipo_servicios = new ArrayList();
The array already loaded from
getlistaTypeServicio ()
I'm trying something like this but it gives me error
List tipo_servicios = Servicios.ConsultarTipoServicios.getlistaTipoServicio();
I solved it this way
consultar = new Servicios.ConsultarTipoServicio();
List tipo_servicios = consultar.getlistaTipoServicio();
List tipo_servicios_enc = new ArrayList();
DTO.Tiposervicio tipo_servicios_select;

Calling different Object's Constructor on each index of Array/Collection

I'm trying to tidy up my code as I have many different classes that need to be initialized before my program is ready to do it's tasks.
They are all optional and can fail, but one of them has to succeed.
All these classes implement an interface called Hook.
Each initialization is put into a HashMap, here is an example:
HashMap<String, Hook> hooks = new HashMap<>();
String key = "Fish";
if (isEnabled(key)) {
try {
hooks.put(key, new FishStoreHook());
} catch {
logError(key);
}
}
But now I have to have another one for, say Bread:
key = "Bread";
if (isEnabled(key)) {
try {
hooks.put(key, new BreadStoreHook());
} catch {
logError(key);
}
}
Is there a way to put something in an array or Collection so that they can be called with a for each statement?
(Reason they are put into a HashMap is because their methods are run with a for each HashMap.keySet(), and I need to log possible errors)
Thank you in advance!
I'd suggest using reflection:
String className = "package.name." + key + "StoreHook";
Class<Hook> clazz = (Class<Hook>) YourClass.class.forName(className);
Hook hook = clazz.newInstance();
OR If you are using Spring, you can also get all sub types of Hook.
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AssignableTypeFilter(Hook.class));
Set<BeanDefinition> definitions = provider.findCandidateComponents("package/name");
Map<String, Hook> hooks = new HashMap<>();
for (BeanDefinition definition : definitions) {
try {
Class clazz = Class.forName(definition.getBeanClassName());
hooks.put(clazz.getSimpleName(), clazz.newInstance());
} catch (ClassNotFoundException e) {
logger.error("Unable to get class: ", e);
}
}
And then you can get your instance from hashmap.
You can add all Hook objects to a List and then use a for-each as shown in the below code with inline comments:
List<Hook> hooks = new ArrayList<>();
hooks.add(new FishStoreHook("Fish"));//Pass HookName as a constructor arg
hooks.add(new BreadStoreHook("Bread"));//Pass HookName as a constructor arg
//add other hook objects
//Now iterate all the hook objects using foreach
for(Hook hook : hooks) {
if(isEnabled(hook.getName())) {//get HookName (set through constrcutor above)
try {
hooks.put(key, hook);
} catch {
logError(key);
}
}
}
#SuppressWarnings( "serial" )
final Map<String, Callable<Hook>> init =
new LinkedHashMap<String, Callable<Hook>>() {{
put( "Fish", new Callable<Hook>() {
#Override public Hook call() throws Exception {
return new FishStoreHook(); }} );
put( "Bread", new Callable<Hook>() {
#Override public Hook call() throws Exception {
return new BreadStoreHook(); }} );
}};
final Map<String, Hook> hooks = new HashMap<>();
for( Map.Entry<String, Callable<Hook>> e: init.entrySet() )
try {
if( isEnabled( e.getKey() ) )
hooks.put( e.getKey(), e.getValue().call() );
} catch( Exception ex ) {
logError( e.getKey() );
}
You need the LinkedHashMap in case you care about the order, otherwise just any kind of Map would do.

Categories

Resources